# 1 - Добро пожаловать, друг :-)

Добро пожаловать в мир Sonic Pi. Надеюсь, что вам настолько же не терпится начать создавать безумные звуки, насколько мне не терпится показать вам, как это делается. Это будет веселое путешествие, в котором ты узнаешь много нового о музыке, синтезе, программировании и производительности программ, композиции и о много другом.

Постойте, как же я мог быть таким невоспитанным! Позвольте мне представиться - я Sam Aaron - тот самый парень, который создал Sonic Pi. Меня можно найти по имени @samaaron в Твиттере, и я был бы очень счастлив обменяться там с вами приветствиями. Вам, возможно, также было бы интересно узнать больше о моих лайв-кодинг выступлениях, где я сам пишу на Sonic Pi перед зрителями.

Если у вас появятся какие-либо мысли или идеи о том, как улучшить Sonic Pi, то, пожалуйста, передайте мне их. Обратная связь - это очень полезно. Никогда не знаешь, вдруг ваша идея может вырасти в нечто действительно большое!

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

Наконец, наблюдать за чужим кодингом в режиме реального времени это отличный способ учиться. Я регулярно вещаю в прямом эфире на http://youtube.com/samaaron, так что не забывайте появляться там, чтобы поприветствовать всех и задать все свои многочисленные вопросы :-)

Что ж, давайте начнём…

# 1.1 - Лайв-кодинг

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

## Расширьте своё сознание

Прежде, чем мы перейдем к деталям того, как Sonic Pi работает, я бы хотел поделиться с вами личным опытом того, что значит “лайв-кодинг”. Не переживайте, если вы пока чего-то из этого (или ничего) не понимаете. Просто держитесь крепче за стул и получайте удовольствие…

## Живой цикл

Для начала скопируйте следующий код в пустой буфер:

    live_loop :flibble do
      sample :bd_haus, rate: 1
      sleep 0.5
    end

Теперь нажмите кнопку `Выполнить`, и вы услышите приятный быстрый барабанный бой. В любой момент нажмите кнопку `Остановить`, чтобы остановить звук. Но не нажимайте её пока что… Вместо этого сделайте вот что:

Убедитесь, что барабаны по-прежнему звучат Измените значение `sleep` с `0.5` на значение побольше, например `1`. Еще раз нажмите кнопку `Выполнить` Можно заметить, что темп барабанов изменился. И, наконец, запомните этот момент - это первый, и, наверняка, не последний ваш лайв-кодинг на Sonic Pi…

Ладно, это было довольно просто. Давайте добавим что-нибудь ещё в наш микс. Сверху от `sample :bd_haus` добавьте строку `sample :ambi_choir, rate: 0.3`. Ваш код должен выглядеть так:

    live_loop :flibble do
      sample :ambi_choir, rate: 0.3
      sample :bd_haus, rate: 1
      sleep 1
    end

Время поиграться. Поменяйте частоту. Что происходит, когда вы используете высокие, малые, или отрицательные значения? Посмотрите, что произойдет, когда вы поменяете значение `rate:` для сэмпла `:ambi_choir` на незначительную величину (например до `0.29`). Что произойдет, если вы выберите очень маленькое значение для `sleep`? Проверьте, получится ли заставить его играть так быстро, что ваш компьютер прекратит свою работу и выдаст ошибку из-за того, что он не справится с этим (если это всё же произошло, то просто выберите значение побольше для `sleep` и снова нажмите `Выполнить`).

Попробуйте закомментировать одну из строк `sample`. Для этого добавьте `#` в ее начало:

    live_loop :flibble do
      sample :ambi_choir, rate: 0.3
    #  sample :bd_haus, rate: 1
      sleep 1
    end

Обратите внимание, компьютер проигнорировал её, поэтому мы её не слышим. Это называется комментарием. В Sonic Pi мы можем использовать комментарии, чтобы убирать или добавлять штуки в микс.

Напоследок, позвольте мне оставить вам кое-что забавное, с чем можно поиграть. Возьмите код, приведенный ниже, и скопируйте его в свободный буфер. Не пытайтесь пока полностью разобраться в нем. Просто обратите внимание, что в нём два цикла - то есть две вещи играют по кругу одновременно. Теперь ваш черёд делать то, что получается у вас лучше всего - экспериментировать и развлекаться. Вот пара советов:

Попробуйте изменить синее значение `rate:`, чтобы услышать, как изменится звук. Попробуйте изменить время для `sleep` и вы услышите, как оба цикла повторяются по кругу с разными темпами. Попробуйте раскомментировать строку примера (удалите знак `#`) и наслаждайтесь звуками гитары на заднем плане. Попробуйте поменять синее значение любого из `mix:` на число в промежутке от `0` (что соответствует исключению из общего микса) до `1` (полностью сочетается).

Не забывайте нажимать `Выполнить`, и вы услышите изменения в следующий раз, когда петля начнётся заново. Не расстраивайтесь, если в конце музыка будет испорчена. Нажмите `Остановить`, удалите код из буфера, вставьте свежую копию, и вы снова готовы к творчеству. На ошибках научиться можно быстрее всего…

Не забывайте нажимать `Выполнить`, вы будете слышать изменения на каждой следующей итерации цикла. Не бойтесь ломать музыкальную композицию. Всегда можно нажать `Остановить`, удалить код из буфера и вставить свежую копию. Не забывайте - процесс творчества тесно связан с совершением ошибок…

    live_loop :guit do
      with_fx :echo, mix: 0.3, phase: 0.25 do
        sample :guit_em9, rate: 0.5
      end
    #  sample :guit_em9, rate: -0.5
      sleep 8
    end
    live_loop :boom do
      with_fx :reverb, room: 1 do
        sample :bd_boom, amp: 10, rate: 1
      end
      sleep 8
    end

Продолжайте играть и экспериментировать до тех пор, пока вам не станет любопытно, как это на самом деле работает, и вы не начнёте думать, что ещё можно сделать. Тогда вы будете готовы к чтению оставшейся части этого учебника.

Так чего же вы ждёте…

# 1.2 - Интерфейс Sonic Pi

У Sonic Pi очень простой интерфейс для кодирования музыки. Мы потратим совсем немного времени на его изучение.

A - Управление воспроизведением B - Управление редактором C - Помощь и справка D - Редактор кода E - Панель настроек F - Просмотр сообщений G - Справочная система F - Просмотр сообщений

## A. Управление Воспроизведением

Эти розовые кнопки - главные элементы для запуска и остановки звука. Есть кнопка Выполнить для запуска кода из редактора, Остановить для остановки всего выполняющегося кода, Сохранить для сохранения кода в файл и Запись для создания записи того, что вы слышите в звуковой файл в формате WAV.

## B. Управление Редактором

These orange buttons allow you to manipulate the code editor. The Size + and Size - buttons allow you to make the text bigger and smaller.

## C. Помощь И Справка

Данные синие кнопки дают вам доступ к информации и настройкам. Кнопка Информация открывает справочное окно, в котором находится информация о самом Sonic Pi - главной команде разработчиков, истории, помощниках и сообществе. Кнопка Помощь включает систему помощи (F), а кнопка Параметры включает панель настроек, где можно менять некоторые базовые параметры приложения.

## D. Редактор Кода

Это область, в которой вы будете писать свой код и сочинять/исполнять музыку. Это простой текстовый редактор, где можно написать код, удалить его, вырезать, вставить и так далее. Представьте, что это простая версия Word или Google Docs. Редактор автоматически раскрасит слова в зависимости от их значения в коде. Поначалу это может казаться странным, но скоро вы увидите, насколько это помогает. К примеру, глядя на что-то синее ты будешь знать, что это число.

## E. Панель Настроек

В Sonic Pi есть множество настраиваемых параметров. Доступ к ним можно получить, нажав кнопку Параметры в наборе кнопок “Помощь и справка”. Она переключит видимость панели настроек, в которой представлено множество вариантов, доступных для изменения. Примерами являются режим моно, инвертированное стерео, включение вывода детальных сообщений, ползунок громкости и выбор аудиовыхода Raspberry Pi.

## F. Просмотр Сообщений

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

## G. Справочная Система

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

## H. Область видимости

В области видимости можно наблюдать за воспроизводимым звуком. Вы с лёгкостью заметите, что пилообразная волна действительно напоминает пилу, а простейшие сигналы выглядят как синусоидальные волны. Вы также можете увидеть разницу между громкими и тихими звуками, глядя на размер выводимых линий. Существует три области видимости, с которыми можно повозиться - стандартная (комбинация левого и правого каналов), стерео (каждый канал обособлен) и, наконец, область видимости фигур Лиссажу, которая показывает отношения фаз левого и правого каналов, а также позволяет создавать красивые изображения при помощи звука. (https://ru.wikipedia.org/wiki/%D0%A4%D0%B8%D0%B3%D1%83%D1%80%D1%8B_%D0%9B%D0%B8%D1%81%D1%81%D0%B0%D0%B6%D1%83).

# 1.3 - Обучение через игру

Sonic Pi стремится воодушевить вас изучать компьютеры и музыку через игру и экспериментирование. Самое главное, чтобы вам было весело, и тогда, прежде, чем вы это поймёте, вы случайно научитесь кодировать, сочинять и исполнять.

## Ошибок не существует

Whilst we’re on this subject, let me just give you one piece of advice I’ve learned over my years of live coding with music - there are no mistakes, only opportunities. This is something I’ve often heard in relation to jazz but it works equally well with live coding. No matter how experienced you are - from a complete beginner to a seasoned live coder, you’ll run some code that has a completely unexpected outcome. It might sound insanely cool - in which case run with it. However, it might sound totally jarring and out of place. It doesn’t matter that it happened - what matters is what you do next with it. Take the sound, manipulate it and morph it into something awesome. The crowd will go wild.

## Начните с простого

Когда вы только учитесь, очень хочется делать удивительные вещи уже сейчас. Но попридержите эту мысль и смотрите на нее, как на далекую цель, которую вы достигнете позже. Пока что, вместо этого думайте о самом простом, что вы можете написать, что было бы забавно и приносило бы некое удовлетворение. Каждый раз это будет небольшим шагом к тому поразительному, что есть в вашем воображении. Как только у вас появилась идея о простом шаге, попробуйте сделать его, играйте с тем, что получилось и разбирайтесь, какие новые идеи он дает вам. Вскоре у вас появится огромное количество способов повеселиться, а обучение пойдет в гору.

Но не забывайте делиться своими достижениями с другими!

# 2 - Синтезаторы

Довольно вступлений. Пора экспериментировать со звуком.

В этой главе мы будем рассматривать основы запуска и управления синтами. Синт - это сокращение от синтезатор, что само по себе означает модное словечко для чего-то, что издает звук. Обычно, синты довольно сложны в использовании (особенно аналоговые, в которых много соединений проводами и модулей). Sonic Pi предоставляет такие же возможности, но очень простым и доступным способом.

Не обманывайтесь кажущейся простотой интерфейса Sonic Pi. С ним, если захочется, можно добраться до самых потаенных глубин очень сложной манипуляции звуком. Итак, придержите свои шляпы…

# 2.1 - Ваши Первые Звуки

Посмотрите на этот код:

    play 70

Отсюда всё берет свое начало. Давайте, скопируйте и вставьте его в окно кода вверху приложения (большое белое пространство под кнопкой `Выполнить`). Затем, нажмите `Выполнить`…

## Звук!

Впечатляет. Нажмите заново. Снова. И снова…

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

    play 75

Слышите разницу? Попробуйте число поменьше:

    play 60

Вот, меньшее число дает более низкий звук, а большее число дает более высокий звук. Прямо как на пианино. Клавиши в нижней части пианино (слева) звучат ниже, а клавиши в верхней части пианино (правая сторона) - выше. На самом деле, числа имеют прямое отношение к клавишам пианино. `play 47` означает “сыграй сорок седьмую ноту на пианино”. То есть `play 48` - это на одну ноту выше (следующая клавиша справа). Так сложилось, что нота “До” четвертой октавы имеет номер 60. Попробуйте сыграть её: `play 60`.

Не волнуйтесь, если для вас это ничего не значит - у меня было то же самое, когда я только начинал. Сейчас важно то, что меньшие числа дают более низкие звуки, а большие числа дают более высокие звуки.

## Аккорды

Играть одну ноту весьма забавно, но играть несколько нот сразу ещё лучше. Попробуйте:

    play 72
    play 75
    play 79

Звучит джазово! Итак, когда вы пишете `play` много раз, все ноты играют в одно и то же время. Попробуйте самостоятельно - какие числа звучат вместе хорошо? Какие звучат ужасно? Экспериментируйте, исследуйте и вы выясните это сами.

## Мелодия

Играть ноты и аккорды весело, а как насчет мелодий? Что, если вы хотите играть одну ноту за другой, а не все вместе? Что же, это легко. Просто нужно вставить `sleep` между ними:

    play 72
    sleep 1
    play 75
    sleep 1
    play 79

Как мило, маленькое арпеджио. Что же значит `1` в `sleep 1`? Ну, это означает продолжительность паузы. Вообще-то, это означает задержку на время одной доли такта, но, пока что будем считать, что это значит спать одну секунду. А вдруг мы захотим, чтобы наше арпеджио стало немного быстрее? Тогда надо указать значение для паузы покороче. Как насчет половины, то есть `0.5`:

    play 72
    sleep 0.5
    play 75
    sleep 0.5
    play 79

Можно заметить: мелодия стала играть быстрее. Попробуйте сами поменять время и используйте разные продолжительности и ноты.

Интересно попробовать значения между нотами, например `play 52.3` или `play 52.63`. Совсем не нужно держаться стандартных целых чисел. Развлекайтесь и получайте удовольствие.

## Обычные названия нот

Для тех, кто уже немного знаком с нотной грамотой (не волнуйтесь, если вы не знаете о чём речь - для веселья она вам не нужна), может быть интересно записать мелодию, используя названия нот, такие как “До” (C) и “Фа-диез” (F#), а не числа. Sonic Pi предусмотрел это. Можно делать так:

    play :C
    sleep 0.5
    play :D
    sleep 0.5
    play :E

Просто помните, что перед нотой должно стоять двоеточие `:`. Тогда она станет розовой. Ещё можно указывать октаву, добавляя её номер после названия ноты:

    play :C3
    sleep 0.5
    play :D3
    sleep 0.5
    play :E4

Если хотите сделать ноту на полтона выше, поставьте `s` после её имени, то есть `play :Fs3`. А когда нужен бемоль, обозначьте это при помощи `b`, то есть `play :Eb3`.

А теперь, дайте себе волю, и как следует повеселитесь, придумывая собственные мелодии.

# 2.2 - Параметры: Amp и Pan

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

## Настройки

Sonic Pi поддерживает регулировки для своих синтезаторов. Они представляют собой элементы управления, для управления которыми вы передаёте атрибуты функции `play`. Эти атрибуты изменяют и контролируют выводимый звук. У каждого синтезатора свой собственный набор регулировок для тонкой настройки звука. Но, есть общие наборы регулировок, одинаковые для разных синтезаторов, такие как `amp:`, `pan:` и параметры огибающей (обсуждается в другой главе).

Каждая регулировка состоит из двух частей: название регулировки (элемента управления) и её значение (деление, на которое вы хотите установить ручку регулировки). Например, может быть настройка с названием `cheese:`, а ее желаемым значением будет `1`.

Настройки передаются вызовам `play` после запятой `,` далее следует название, например `amp:` (не забудьте двоеточие `:`), а потом ее значение. Например:

    play 50, cheese: 1

(Замечание: `cheese:` - не настоящая настройка, мы просто используем ее для примера).

Можно передавать много настроек, разделяя их запятыми:

    play 50, cheese: 1, beans: 0.5

Порядок регулировок не важен, так что следующий пример ничем не отличается:

    play 50, beans: 0.5, cheese: 1

Регуляторы, о которых синтезатор не знает, попросту пропускаются (такие как `cheese` и `beans` - очевидно нелепые названия для настроек!)

Если вы случайно укажите одну и ту же настройку с разными значениями, то победит последнее. Например, значением `beans:` будет `2`, а не `0.5`:

    play 50, beans: 0.5, cheese: 3, eggs: 0.1, beans: 2

Множество вещей в Sonic Pi гибко регулируемо, потратьте немного времени на изучение того, как использовать их, и будете “настроены”! Давайте позабавимся с нашим первым регулятором - `amp:`.

## Амплитуда

Амплитуда - компьютерное представление громкости звука. Высокая амплитуда даёт громкий звук, а низкая амплитуда даёт тихий звук. Так же, как Sonic Pi использует числа для обозначения нот, числами обозначается и амплитуда. При значении амплитуды 0 получается тишина (ничего не будет слышно), а амплитуда 1 - это нормальная громкость. Можно, также, увеличить амплитуду до 2, 10 или 100. Но стоит отметить, что когда общая амплитуда становится слишком высокой, то Sonic Pi включает так называемый компрессор, чтобы сжать ее и не дать звуку сделаться слишком громким для ваших ушей. Часто это может делать звук непонятным и странным. Так что постарайтесь использовать значения амплитуды в промежутке от 0 до 0.5, чтобы избегать компрессии.

## Усиление

Чтобы изменить амплитуду звука, можно воспользоваться настройкой `amp:`. Например, передай 0.5, чтобы играть на половинной громкости:

    play 60, amp: 0.5

Чтобы играть на удвоенной громкости, передай 2:

    play 60, amp: 2

Регулировка `amp:` изменяет тот вызов `play`, с которым она идёт вместе. Поэтому в следующем примере первый вызов произойдет на половинной громкости, а второй вернется к значению по умолчанию (1):

    play 60, amp: 0.5
    sleep 0.5
    play 65

Конечно, можно задавать разные значения `amp:` для каждого вызова `play`:

    play 50, amp: 0.1
    sleep 0.25
    play 55, amp: 0.2
    sleep 0.25
    play 57, amp: 0.4
    sleep 0.25
    play 62, amp: 1

## Панорамирование

Еще одной забавной настройкой, которую стоит использовать, является `pan:`. Она контролирует смещение звука в стереобазе. Смещение звука влево означает, что вы услышите его из левого динамика, а смещение вправо - что он будет выходить из правого динамика. Мы используем -1 для полного смещения влево, 0 для центра, а 1 - для полного смещения вправо в стереобазе. Безусловно, мы можем указывать любое значение в промежутке между -1 и 1 для точного позиционирования нашего звука.

Давай получим звук из левого динамика:

    play 60, pan: -1

Теперь, повторим его из правого:

    play 60, pan: 1

Наконец, выведем его снова по центру (позиция по умолчанию):

    play 60, pan: 0

Попробуйте сами сделать что-нибудь весёлое, меняя амплитуду и панорамирование ваших звуков!

# 2.3 - Переключаем Синтезаторы

До сего момента мы, по большей части, развлекались с простыми звуками. Однако, простые тона уже начали вас утомлять. Разве это все, что Sonic Pi может предложить? Определенно, у лайвкодинга есть больше возможностей, чем просто гудение. Да, есть. И в этой главе мы познакомимся с захватывающим набором звуков, доступных в Sonic Pi.

## Синтезаторы

В Sonic Pi есть ряд инструментов, называемых синтами, что есть сокращение от термина “синтезатор”. В то время, как сэмплы представляют собой предварительно записанные звуки, синты могут генерировать новые звуки в зависимости от того, как вы ими управляете (это мы изучим далее в этом учебнике). Синты Sonic Pi - очень могущественные и яркие инструменты. Играть с ними очень весело. Вначале, давайте научимся выбирать какой синтезатор мы будем использовать.

## Жужжащие Пилы И Профеты

Пилообразная волна - забавный звук. Давайте попробуем его:

    use_synth :saw
    play 38
    sleep 0.25
    play 50
    sleep 0.25
    play 62
    sleep 0.25

Попробуйте другой - prophet:

    use_synth :prophet
    play 38
    sleep 0.25
    play 50
    sleep 0.25
    play 62
    sleep 0.25

Как насчет смешивания обоих. Сначала один, а потом другой:

    use_synth :saw
    play 38
    sleep 0.25
    play 50
    sleep 0.25
    use_synth :prophet
    play 57
    sleep 0.25

А теперь вместе:

    use_synth :tb303
    play 38
    sleep 0.25
    use_synth :dsaw
    play 50
    sleep 0.25
    use_synth :prophet
    play 57
    sleep 0.25

Как вы могли заметить, команда `use_synth` влияет только на следующие вызовы `play`. Представьте, что это большой выключатель - новые вызовы `play` будут играть только на используемом синте. На новый синт можно переключиться с помощью `use_synth`.

## Изучаем синтезаторы

To see which synths Sonic Pi has for you to play with take a look at the Synths option in the menu at the bottom of this help screen (between Examples & Fx). There are over 20 to choose from. Here are a few of my favourites:

`:prophet` `:dsaw` `:fm` `:tb303` `:pulse`

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

# 2.4 - Управление длительностью при помощи огибающих

В одной из предыдущих глав мы изучали, как можно использовать команду `sleep` для того, чтобы контролировать, когда начинается звук. Однако, до этого момента мы не могли настраивать продолжительность наших звуков.

В качестве простого и мощного способа управления длительностью наших звуков Sonic Pi предоставляет нам понятие ADSR амплитудной огибающей (Дальше в этой главе - ADSR). Амплитудная огибающая предлагает контроль по двум параметрам:

управление длительностью звука управление амплитудой звука

## Длительность

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

## Амплитуда

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

Итак, как мы видели раньше, амплитуда 0 - это тишина, а амплитуда 1 - нормальная громкость.

Теперь, пришла пора взглянуть на каждую часть огибающей по порядку.

## Фаза затухания (Release Phase)

Единственная часть огибающей, установленная по умолчанию, - это время затухания. Оно обозначает продолжительность времени, за которое звук полностью исчезнет. У всех синтов затухание настроено на 1, что значит по умолчанию звук длится в течение одной доли такта (что при темпе по умолчанию в 60 составляет 1 секунду):

    play 70

Ноту будет слышно одну секунду. Можете измерить сами :-) В полной, и более явной записи, то же самое будет выглядеть так:

    play 70, release: 1

Заметьте, что звук получился точно таким же (длился ровно 1 секунду). Очень легко изменять длительность, изменяя значение регулировки `release:`:

    play 60, release: 2

Можно cделать звучание синта крайне непродолжительным, указав очень маленькое значение затухания:

    play 60, release: 0.2

Длительность затухания звука называется фазой затухания (release phase) и, по умолчанию, представляет из себя линейный переход (т.e. прямую линию). Следующая диаграмма иллюстрирует такой переход:

Вертикальная линия на левом краю диаграммы показывает, что звук начинается при амплитуде 0, но сразу после этого начинает выводиться на полной громкости (это фаза атаки, которую мы рассмотрим далее). Как только достигнута максимальная амплитуда, она спадает прямой линией до нуля, занимая время, указанное для `release:`. Чем продолжительнее время затухания, тем дольше будет стихать синт

Таким образом, вы можете менять длительность звучания своих звуков, изменяя время затухания. Потратьте немного времени, пробуя добавлять время затухания к собственной музыке.

## Фаза атаки (Attack Phase)

По умолчанию фаза атаки равна 0 для всех синтов, что значит их амплитуда меняется от 0 до 1 мгновенно. Поэтому начальный звук синта похож на удар. Но вам может понадобиться плавно вывести звук. Этого можно добиться при помощи регулировки `attack:`. Попробуйте плавно извлекать какие-нибудь звуки:

    play 60, attack: 2
    sleep 3
    play 65, attack: 0.5

Можно пользоваться несколькими регуляторами в одно и то же время. Например, для короткой атаки и долгого затухания попробуйте:

    play 60, attack: 0.7, release: 4

Эта краткая атака и длинное затухание иллюстрируются следующей диаграммой:

Конечно, можно и наоборот. Попробуйте долгую атаку и короткое затухание:

    play 60, attack: 4, release: 0.7

В конце-концов, для кратких звуков можно сделать короткими и атаку, и затухание.

    play 60, attack: 0.5, release: 0.5

## Фаза задержки (Sustain Phase)

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

    play 60, attack: 0.3, sustain: 1, release: 1

Задержка полезна для важных звуков, которые вы хотели бы полностью выделить при сведении, прежде чем они перейдут в необязательную фазу затухания. Конечно же, совершенно допустимо устанавливать и `attack:` и `release:` в 0 и попросту использовать задержку, чтобы не иметь абсолютно никакого нарастания и затухания у звука. Но стоит заметить, что затухание 0 может давать щелчки в аудио, и часто лучше все-таки указывать очень маленькое значение, такое как 0.2.

## Фаза спада (Decay Phase)

Для дополнительного уровня контроля можно указать время спада. Это фаза огибающей, которая помещается между фазами атаки и задержки. Она задает участок времени, когда амплитуда будет падать от уровня `attack_level:` до `decay_level:` (если явно не установить его, то он будет совпадать с `sustain_level:`). По умолчанию, уровни `decay:` и `attack:` установлена в 0, а уровень затухания в 1, поэтому надо указывать время спада, чтобы оно имело какой-либо эффект:

    play 60, attack: 0.1, attack_level: 1, decay: 0.2, sustain_level: 0.4, sustain: 1, release: 0.5

## Уровень спада (Decay Level)

Еще один, последний трюк, состоит в том, что хотя настройки `decay_level:` изначально совпадают со значением `sustain_level:`, вы можете явно присвоить им разные значения для полного контроля над огибающей. Это позволяет создавать огибающие наподобие следующей:

    play 60, attack: 0.1, attack_level: 1, decay: 0.2, decay_level: 0.3, sustain: 1, sustain_level: 0.4, release: 0.5

Можно, к тому же, устанавливать `decay_level:` выше, чем `sustain_level:`:

    play 60, attack: 0.1, attack_level: 0.1, decay: 0.2, decay_level: 1, sustain: 0.5, sustain_level: 0.8, release: 1.5

## ADSR-огибающие

Итак, подведем итог. ADSR-огибающие в Sonic Pi состоят из следующих фаз:

Attack - атака - время, за которое амплитуда растет от 0 до `attack_level`, Decay - спад - время, когда амплитуда переходит от `attack_level` до `decay_level`, Sustain - задержка - время изменения амплитуды с `decay_level` на `sustain_level`, Release - затухание - время падения амплитуда с `sustain_level` до 0

Важно помнить, что длительность звука - это сумма продолжительностей всех фаз. Соответственно, такой звук будет длиться 0.5 + 1 + 2 + 0.5 = 4 доли такта:

    play 60, attack: 0.5, attack_level: 1, decay: 1, sustain_level: 0.4, sustain: 2, release: 0.5

Теперь пришло время поиграть с огибающими, добавляя их в свои звуки…

# 3 - Сэмплы

Другой отличный способ сочинять музыку - использовать заранее записанные звуки. В лучших традициях хип-хопа, мы называем такие записанные звуки сэмплами. То есть, если вы возьмёте микрофон, выйдете наружу и запишете мягкие звуки ударов дождя о навес, вы создадите сэмпл.

В Sonic Pi можно делать много забавных вещей с сэмплами. Помимо 90 встроенных сэмплов со свободной лицензией, программа даёт вам работать и играть с собственными. Перейдем же к делу..

# 3.1 - Воспроизведение cэмплов

Простые звуки - это только начало. Кое-что весьма весёлое - это проигрывание сэмплов. Попробуйте:

    sample :ambi_lunar_land

Sonic Pi включает множество сэмплов. Их можно использовать так же, как вы используете команду `play`. Чтобы проиграть несколько сэмплов и нот, просто запишите их друг под другом:

    play 36
    play 48
    sample :ambi_lunar_land
    sample :ambi_drone

Если их нужно разделить во времени, используйте команду `sleep`:

    sample :ambi_lunar_land
    sleep 1
    play 48
    sleep 0.5
    play 36
    sample :ambi_drone
    sleep 1
    play 36

Обратите внимание, что Sonic Pi не ждёт, пока закончится один звук, прежде чем начать играть следующий. Команда `sleep` всего лишь описывает разделение моментов, когда звуки начинаются. За счет этого их можно легко совмещать, создавая интересные эффекты наложения. Далее в этом учебнике мы рассмотрим управление длительностью звуков при помощи огибающих.

## Знакомимся с сэмплами

There are two ways to discover the range of samples provided in Sonic Pi. First, you can use this help system. Click on Samples in the menu at the bottom of this help screen, choose your category and then you’ll see a list of available sounds.

С другой стороны, можно задействовать систему автодополнения. Просто начните набирать название группы сэмплов, например `sample :ambi_`, и появится выпадающее меню с названиями сэмплов на выбор. Попробуйте такие варианты приставки:

`:ambi_` `:bass_` `:elec_` `:perc_` `:guit_` `:drum_` `:misc_` `:bd_`

Попробуйте создать собственные композиции из сэмплов!

# 3.2 - Параметры сэмплов: Амплитуда и Панорамирование

Также, как и с синтами, мы можем легко контролировать наши сэмплы при помощи параметров. Механизм передачи параметров сэмплам точно такой же. Вспомним наших друзей `amp:` и `pan:`.

## Усиливаем сэмплы

Можно менять амплитуду сэмплов точно так же, как и синтов:

    sample :ambi_lunar_land, amp: 0.5

## Панорамируем сэмплы

Ещё один параметр сэмплов, доступный для использования - `pan:`. Например, вот так мы бы сыграли амен-брейк в левом канале, а потом на середине проиграли бы его снова, но в правом канале:

    sample :loop_amen, pan: -1
    sleep 0.877
    sample :loop_amen, pan: 1

Обратите внимание, что 0.877 - это половина продолжительности сэмпла в секундах.

Наконец, если вы сбросите регулировки какого-нибудь синта на настройки по умолчанию, (как это сделать при помощи `use_synth_defaults`, рассмотрим далее), то сэмпл не обратит на это внимания.

# 3.3 - Растягиваем сэмплы

Раз уж теперь мы умеем играть на разнообразных синтах и воспроизводить всевозможные сэмплы, пришло время научиться управлять ими обоими, чтобы музыка получалась ещё более уникальной и интересной. Вначале, давайте рассмотрим возможность растягивать и сжимать сэмплы.

## Представление сэмпла

Сэмплы - это предварительно записанные звуки в виде чисел, описывающих, как колеблется мембрана динамика, чтобы воспроизвести звук. Мембрана движется внутрь и наружу, так что числами всего лишь нужно задать насколько втянутой или выпуклой она должна быть в каждый момент времени. Для правдоподобного воспроизведения звука, обычно сэмпл хранит много тысяч чисел для каждой секунды! Sonic Pi берет список этих чисел и передаёт их с нужной скоростью, чтобы двигать мембраной динамика наружу и внутрь так, чтобы получился нужный звук. Но можно неплохо поразвлечься, меняя звук за счет изменения скорости, с которой числа идут в динамик.

## Меняем скорость

Попробуем проверить это на одном из природных звуков: `:ambi_choir`. Чтобы воспроизвести его с обычной скоростью, можно передавать команде `sample` настройку `rate:`:

    sample :ambi_choir, rate: 1

Этот пример воспроизводит сэмпл с нормальной скоростью (1). Пока что ничего особенного. Однако, мы можем свободно изменить это число на что-то другое. Как насчет `0.5`:

    sample :ambi_choir, rate: 0.5

Ого! Это что такое происходит? Ну, две вещи. Во-первых - сэмпл воспроизводится в два раза дольше. Во-вторых - звук стал ниже на октаву. Давайте разберём это более детально.

## Давайте растянем

Сэмпл, который забавно растягивать и сжимать, - это амен-брейк. С нормальной скоростью мы можем легко себе представить его в составе трека драм-н-бейс:

    sample :loop_amen

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

    sample :loop_amen, rate: 0.5

А если ускориться, то мы попадаем на территорию джангл:

    sample :loop_amen, rate: 1.5

А теперь гвоздь программы - проверим, что произойдет, если мы зададим отрицательную скорость:

    sample :loop_amen, rate: -1

Ничего себе! Он стал играть задом-наперёд! Попробуйте воспроизвести разные сэмплы на разных скоростях. Попробуйте очень быстрые скорости. Попробуйте несуразно медленные. Узнайте, какие интересные звуки можно создать.

## Простое объяснение скорости сэмпла

Полезная мысленная аналогия сэмплам - пружина. Темп воспроизведения - это как сжатие и растягивание пружины. Если воспроизводить сэмпл со скоростью 2, то вы будете сжимать пружину до половины ее нормальной длины. Следовательно, воспроизведение сэмпла займёт половину времени, ведь он стал короче. Если играть сэмпл на половине обычной скорости, то вы растягиваете пружину в два раза. Поэтому сэмпл длится в два раза дольше, ведь он стал длиннее. Чем больше вы сдавливаете, тем короче он получается (скорость выше), а чем больше вы растягиваете, тем длиннее он становится (скорость ниже).

Сжатие пружины увеличивает ее плотность (число витков на сантиметр) - это совпадает с тем, почему сэмпл начинает звучать с высокой частотой. Растягивание пружины снижает ее плотность, и это похоже на то, как частота звука понижается.

## Математика, объясняющая скорость сэмпла

(Эта часть приведена для тех, кому интересны детали. Всем остальным её можно пропустить…)

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

Вы могли видеть похожие картинки до этого. Они называются волновой формой сэмпла. Это просто числовой график. Обычно подобные формы включают 44100 точек с данными на каждую секунду времени (из-за теоремы сэмплирования Найквиста-Шэннона). Итак, если сэмпл длится две секунды, то форма волны будет состоять из 88200 чисел, которые мы бы передавали динамической головке со скоростью 44100 значения в секунду. Конечно, мы могли бы удвоить темп передачи, тогда воспроизведение бы заняло всего одну секунду. А еще мы могли бы проигрывать его в два раза медленнее, что означало бы 22500 точек в секунду, и весь процесс бы занял четыре секунды.

На длительность сэмпла влияет скорость воспроизведения:

Удвоение темпа уполовинивает время воспроизведения, Сокращение темпа вдвое удваивает время воспроизведения, Если задать темп, равный четверти от нормального, то время учетверится, Если скорость воспроизведения равна 1/10 от нормальной, то время воспроизведения увеличится в 10 раз.

Мы можем представить это отношение формулой:

    новая_длительность_сэмпла = (1 / скорость) * длительность_сэмпла

Изменение темпа воспроизведения, к тому же, влияет на высоту сэмпла. Частота формы сигнала и высота звука определяются тем, как часто сигнал движется вверх и вниз. Наш мозг каким-то образом превращает быстрые перемещения мембраны в высокие ноты, а медленные - в низкие. Именно поэтому иногда вы можете видеть вибрации большого басового динамика, когда он издает чрезвыйчайно низкие звуки. На самом деле он перемещается намного медленнее внутрь и наружу, чем динамик, воспроизводящий высокие ноты.

Если взять форму сигнала и сжать ее, то она будет колебаться вверх и вниз большее количество раз за секунду. За счет этого звук получится более высоким. Выходит, что удвоение движений вверх-вниз (колебаний) удваивает частоту. Поэтому проигрывание сэмпла на удвоенной скорости удваивает его слышимую частоту. Точно так же половинная скорость уменьшает частоту вдвое. Другие значения скорости влияют на частоту соответсвующе.

# 3.4 - Огибающие сэмплов

Также возможно изменять длительность и амплитуду сэмпла, используя ADSR-огибающие. Но это работает немного по-другому, чем ADSR-огибающие синтов. Огибающие сэмплов позволяют уменьшать громкость и длительность, но не увеличивать их. Сэмпл остановится, либо когда его воспроизведение завершено, либо когда огибающая закончилась - в зависимости от того, что произошло раньше. Так что если задать очень долгое затухание, то звучание сэмпла не удлинится.

## Огибающие амен

Вернемся к нашему верному другу амен-брейку:

    sample :loop_amen

Без дополнительных регулировок мы слышим полный сэмпл на полной громкости. Если мы хотим его постепенно усиливать в течение одной секунды, то можно задейстовать параметр `attack:`:

    sample :loop_amen, attack: 1

Для более краткого нарастания, выберите значение атаки поменьше:

    sample :loop_amen, attack: 0.3

## Автоудержание

Отличие поведения ADSR-огибающей сэмпла от стандартной огибающей синта лежит в значении сустейна. В обычной огибающей синта сустейн сам по себе устанавливался в 0, если мы не указывали его вручную. Для сэмплов оно также настраивается “автомагически”, и равняется времени, необходимому для завершения сэмпла. Поэтому мы слышим полный сэмпл, когда никаких настроек не задаётся. Если бы значения атаки, спада, удержания и затухания равнялись 0, то мы бы и намёка на сэмпл не услышали. Так что Sonic Pi вычисляет сколько времени длится сэмпл, вычитает длительности атаки, спада и затухания, и присваивает результат фазе удержания. Если атака, спад и затухание вместе дают значение больше продолжительности сэмпла, то удержание устанавливается в 0.

## Постепенное затухание

Для изучения этого явления рассмотрим наш амен-брейк более детально. Если спросить Sonic Pi сколько длится сэмпл:

    print sample_duration :loop_amen

Он напечатает `1.753310657596372`, что означает собственное время звучания сэмпла в секундах. Просто для удобства округлим его до `1.75`. Затем, если установить затухание в `0.75`, произойдет кое-что неожиданное:

    sample :loop_amen, release: 0.75

Первая секунда сэмпла будет воспроизводиться на полной громкости, а потом последует постепенное затухание в течение 0.75 секунды. Это и есть пример автоудержания в действии. Само по себе затухание всегда работает с конца сэмпла. Если бы наш сэмпл длился 10.75 секунды, то первые 10 секунд он бы играл с полной амплитудой, а потом затухал оставшиеся 0.75 секунды.

Запомните: по умолчанию `release:` отсчитывает затухание от конца сэмпла.

## Постепенное усиление и затухание

Можно использовать вместе `attack:`, `release:` и поведение автоудержания для постепенного усиления и затухания при воспроизведении сэмпла:

    sample :loop_amen, attack: 0.75, release: 0.75

Так как полная продолжительность равняется 1.75 секунды, а наши фазы атаки и затухания суммарно дают 1.5 секунды, то удержание автоматически устанавливается в 0.25 секунды. Так мы легко можем плавно усиливать и гасить сэмпл.

## Точное удержание

Вернуться к нормальному режиму ADSR-огибающей довольно просто: достаточно вручную задать 0 для `sustain:`:

    sample :loop_amen, sustain: 0, release: 0.75

После этого сэмпл звучит в общей сложности всего лишь 0.75 секунды. При обычных нулевых значениях `attack:` и `decay:` громкость сэмпла сразу же достигает полного значения, удерживается там в течение 0 секунд, а потом за 0.75 секунды полностью затихает во время фазы затухания.

## Тарелки

Хороший эффект от данного поведения получается, если мы хотим превратить продолжительные сэмплы в более короткие. Это даст им более отрывистое ударное звучание. Рассмотрим сэмпл `:drum_cymbal_open`:

    sample :drum_cymbal_open

Можно слышать, что тарелка продолжает звенеть некоторое время. С помощью огибающей можно сделать её более резкой:

    sample :drum_cymbal_open, attack: 0.01, sustain: 0, release: 0.1

А еще можно изображать удар по тарелке и его глушение за счет увеличения периода удержания:

    sample :drum_cymbal_open, attack: 0.01, sustain: 0.3, release: 0.1

А теперь, ступайте, и как следует позабавьтесь, добавляя огибающие к сэмплам. Попробуйте изменять и скорость, чтобы получить действительно интересные результаты.

# 3.5 - Фрагментированные сэмплы

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

    sample :loop_amen

Потом мы рассмотрели то, как мы можем менять темп сэмплов, например для воспроизведения их на половинной скорости:

    sample :loop_amen, rate: 0.5

Затем, мы увидели, как можно постепенно усиливать сэмпл (совместим это с уменьшённой вдвое скоростью):

    sample :loop_amen, rate: 0.5, attack: 1

Еще мы узнали как сделать начало сэмпла более резким за счет задания `sustain:` явного значения и установки коротких атаки и затухания:

    sample :loop_amen, rate: 2, attack: 0.01, sustain: 0, release: 0.35

Однако, вам бы понравилось, если бы не надо было всякий раз начинать сэмпл с начала? Разве не здорово было бы, если бы можно было играть сэмпл не до конца?

## Выбираем точку старта

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

    sample :loop_amen, start: 0.5

А как насчет последней четверти:

    sample :loop_amen, start: 0.75

## Выбираем точку окончания

Похожим образом разрешается выбирать конечную точку сэмпла как значение между 0 и 1. Прервем амен-брейк на середине:

    sample :loop_amen, finish: 0.5

## Указываем начало и конец

Естественно, мы можем комбинировать обе этих регулировки, чтобы проигрывать произвольные сегменты аудио-файла. Что, если выбрать небольшой участок в центре:

    sample :loop_amen, start: 0.4, finish: 0.6

Что случится, если установить старт после финиша?

    sample :loop_amen, start: 0.6, finish: 0.4

Круто! Он играет задом-наперед!

## Соединяем со скоростью

Можно объединить эту новую способность играть выбранные сегменты аудио с нашим знакомым `rate:`. Например, таким образом воспроизведется очень маленькая секция из середины амен-брейка очень медленно:

    sample :loop_amen, start: 0.5, finish: 0.7, rate: 0.2

## Соединяем с огибающими

Наконец, все это возможно соединить с известными нами ADSR-огибающими, чтобы получить интересный результат:

    sample :loop_amen, start: 0.5, finish: 0.8, rate: -0.2, attack: 0.3, release: 1

Попробуйте также комбинировать сэмплы, не ограничивайте свою фантазию…

# 3.6 - Внешние сэмплы

Коль скоро встроенные сэмплы дали тебе быструю возможность разобраться с ними, тебе может захотеться поэкспериментировать с другими записанными звуками в твоей музыке. Sonic Pi полностью поддерживает эту функцию. Но сперва кратко обсудим переносимость твоего произведения.

## Портативность

Когда ты сочиняешь свои композиции только с использованием встроенных синтов и сэмплов, то программный код - это все что нужно для надежного исполнения твоей музыки. Просто задумайся над этим на минуту - это же просто удивительно! Простой кусок текста, который можно отправить по электронной почте или засунуть в Gist являет собой все, что нужно для воспроизведения твоих звуков. Поэтому их очень легко распространять среди твоих друзей, потому что им всего лишь нужно заполучить код.

С другой стороны, если начинать использовать собственные записанные сэмплы, то такая переносимость теряется. Это происходит из-за того, что для воспроизведения твоей музыки другим людям не только нужен твой код, но также и сэмплы. Этот факт ограничивает других в их возможностях изменять и экспериментировать с твоими работами. Конечно, знание этого не должно тебя останавливать от использования собственных сэмплов. Просто помни об этом.

## Локальные сэмплы

Так как все-таки проиграть любой WAV, AIFF или FLAC с твоего компьютера? Все что нужно, это передать путь к его файлу команде `sample`:

    # Raspberry Pi, Mac, Linux
    sample "/Users/sam/Desktop/my-sound.wav"
    # Windows
    sample "C:/Users/sam/Desktop/my-sound.wav"

Sonic Pi автоматически загрузит и воспроизведет сэмпл. Вместе с этим можно передавать все стандартные параметры, которые ты привык использовать с `sample`:

    # Raspberry Pi, Mac, Linux
    sample "/Users/sam/Desktop/my-sound.wav", rate: 0.5, amp: 0.3
    # Windows
    sample "C:/Users/sam/Desktop/my-sound.wav", rate: 0.5, amp: 0.3

# 3.7 - Наборы сэмплов

Замечание: этот раздел руководства рассказывает о расширенных возможностях работы с большими директориями ваших собственных сэмплов. Рекомендуем ознакомится с ним в тех случаях, если вы загрузили или купили набор сэмплов и хотите использовать их в 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"

Тем не менее, оба этих вызова требуют от нас знания имён сэмплов внутри нашей директории. Что если мы просто хотим быстро прослушать каждый сэмпл по очереди?

## Индексирование наборов сэмплов

Если мы хотим проиграть первый сэмпл в директории, мы просто должны указать имя директории в `sample` и установить индекс в значение `0` следующим образом:

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

Мы также можем создать ярлык (shortcut) нашей директории, используя переменную:

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

Теперь, если мы хотим проиграть второй сэмпл в директории, нам нужно прибавить 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`

Заметьте, что в их именах содержится некоторая информация. Во-первых, у нас есть BMP сэмпла (удары в секунду) в начале имени. Таким образом, сэмпл пианино имеет BPM равный 120, а первые три мелодии - 100 BPM. Имена сэмплов также содержат тональность. Таким образом, гитарный сэмпл имеет тон Bb а мелодии A#. Эта информация очень полезна для сведения этих сэмплов в нашем коде. Например, мы знаем, что сэмпл пианино содержит 120 BPM и тональность Bb.

Оказывается, мы можем использовать это конкретное соглашение об именах наших наборов сэмплов в коде, чтобы помочь нам отфильтровать те, которые нам нужны. Например, если мы работаем с 120 BPM, мы можем отфильтровать все образцы, содержащие строку `120`, со следующим:

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

Первое совпадение будет проиграно. Если мы хотим, чтобы заиграло второе совпадение, нам нужно просто изменить индекс:

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

Более того, мы можем использовать несколько фильтров сразу. Например, если мы хотим сэмпл, имя которого содержит подстроки “120” и “A#”, мы можем легко добиться этого следующим кодом:

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

Наконец, мы по-прежнему можем добавлять свойства к вызову нашего `сэмпла`:

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

## Источники

Система аргументов фильтров сэмплов понимает два типа информации: источники и фильтры. Источники представляют собой информацию, используемую для создания списка потенциальных совпадений. Источники бывают двух видов:

“/path/to/samples” - строка, представляющая валидный путь к директории “/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

Например, здесь мы комбинируем сэмплы из двух каталогов и добавляем конкретный сэмпл. Если `"/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` - Числа будут выбирать совпадение с этим индексом (зацикливаться, если необходимо).

Например, мы можем отфильтровать все образцы в каталоге, содержащем строку `"foo"`, и воспроизвести первый совпадающий образец на половинной скорости:

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

См. Справку по `sample` для множества подробных примеров использования. Обратите внимание, что порядок фильтров соблюдается.

## Composites

Наконец, вы можете использовать списки везде, где вы можете разместить источник или фильтр. Список будет автоматически сплющиваться, и содержимое будет рассматриваться как обычные источники и фильтры. Поэтому следующие вызовы `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#"]]]

## Подведение итогов

Это расширенный раздел для людей, которым нужны дополнительные возможности для манипулирования и использования наборов сэмплов. Если большая часть этого раздела не имеет особого смысла, не беспокойтесь. Скорее всего, вам пока не нужна какая-либо из этих функций. Однако, вы будете знать, когда это понадобится, и вы можете вернуться и перечитать это, когда начнете работать с большими каталогами сэмплов.

# 4 - Рандомизация

Отличный способ сделать вашу музыку несколько более интересной - это использовать случайные числа. В 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

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

    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)`:

87.5054931640625 86.05255126953125 61.77825927734375

## rrand_i

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

88 86 62

## rand

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

    loop do
      play 60, amp: rand
      sleep 0.25
    end

## rand_i

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

## dice

Иногда нужно изобразить бросание игральных костей - это частный случай `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`, которые мы рассмотрим в одной из следующих глав нашего учебника.

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

# 5 - Программирование структур

После того, как мы изучили основы создания звука при помощи `play` и `sample`, и сочинения простых мелодий и ритмов, расставляя задержки между ними, вам могло стать интересно, а что же ещё мир программирования может нам предложить…

Скажем так, вас ожидает захватывающее путешествие! Оказывается, что основные структуры программирования, такие как циклы, условные выражения, функции и потоки выполнения, предлагают нам очень мощные инструменты для выражения собственных музыкальных идей.

Ограничимся лишь основами…

# 5.1 - Блоки

Структура, которая будет попадаться вам в Sonic Pi особенно часто, - это блок. Блоки позволяют нам делать разные полезные вещи с большими участками кода. Например, при помощи параметров синтов и сэмплов мы могли изменять что-то, что происходило в одной строке. Однако, иногда нам нужно сделать что-то значительное, что касается множества строк кода. Например, мы можем решить играть их по кругу, добавить эффект реверберации всего к одному из пяти повторов и так далее. Рассмотрим следующий код:

    play 50
    sleep 0.5
    sample :elec_plip
    sleep 0.5
    play 62

Чтобы сделать что-то с куском кода, нам надо сказать Sonic Pi, где этот блок кода начинается, и где он заканчивается. Для его начала мы используем `do`, а для обозначения конца - `end`. Пример:

    do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

Все же он ещё не является завершённым и не будет работать (попробуйте и получите сообщение об ошибке), так как мы не сообщили Sonic Pi, что мы хотим делать с этим блоком *do/end. Этого можно добиться, если написать некий специальный код перед `do`. Далее мы увидим много примеров этих специальных кусочков кода. Пока лишь важно понять, что оборачивание вашего кода в `do` и `end` сообщает Sonic Pi, что вы хочтите сделать что-то особенное с этим блоком.

# 5.2 - Итерации и циклы

До этого момента мы потратили немало времени, пробуя разные звуки, которые можно производить внутри блоков `play` и `sample`. Мы также изучили как разносить эти звуки во времени, используя `sleep`.

Как мы уже смогли выяснить, даже с этими простейшими блоками кода можно долго забавляться. Однако, совершенно новое измерение веселья откроется для вас, когда вы начнёте использовать мощь блоков кода для структурирования вашей музыки. В нескольких последующих главах мы рассмотрим некоторые из этих новых инструментов. Вначале идут итерации и циклы.

## Повторение

Доводилось ли вам писать код, который вы бы хотели повторить несколько раз? Например, у вас могло получиться нечто подобное:

    play 50
    sleep 0.5
    sample :elec_blup
    sleep 0.5
    play 62
    sleep 0.25

Что, если мы захотим повторить это три раза? Что ж, можно было бы выбрать простейший путь и попросту продублировать код трижды:

    play 50
    sleep 0.5
    sample :elec_blup
    sleep 0.5
    play 62
    sleep 0.25
    play 50
    sleep 0.5
    sample :elec_blup
    sleep 0.5
    play 62
    sleep 0.25
    play 50
    sleep 0.5
    sample :elec_blup
    sleep 0.5
    play 62
    sleep 0.25

Этот код просто огромен! Как быть, если нам захочется поменять сэмпл на `:elec_plip`? Придется найти все места с изначальным `:elec_blup` и переписать их. Что ещё важнее, каким образом повторить кусок кода 50 раз или 1000? Это было бы и впрямь целая куча кода. Гигантское число строк пришлось бы изменять для каждой правки.

## Итерации

На самом деле сделать повторение кода должно быть не сложнее, чем сказать сделай это три раза. В общем-то, так оно и есть. Помните ли вы о нашем старом знакомом, блоке кода? Его можно использовать для отметки начала и конца кода, который необходимо повторить три раза. Мы добавим специальную конструкцию `3.times`. Так что, вместо записи делай это три раза, мы напишем `3.times do`. Это не очень сложно. Просто не забывайте указать `end` в конце кода, который надо повторить:

    3.times do
      play 50
      sleep 0.5
      sample :elec_blup
      sleep 0.5
      play 62
      sleep 0.25
    end

Ну, разве это не лучше дублирования? Много красивых структур может быть создано с использованием этой инструкции:

    4.times do
      play 50
      sleep 0.5
    end
    8.times do
      play 55, release: 0.2
      sleep 0.25
    end
    4.times do
      play 50
      sleep 0.5
    end

## Вложенные Итерации

Еще можно поместить итерации внутрь других итераций и получить интересный рисунок. Например:

    4.times do
      sample :drum_heavy_kick
      2.times do
        sample :elec_blip2, rate: 2
        sleep 0.25
      end
      sample :elec_snare
      4.times do
        sample :drum_tom_mid_soft
        sleep 0.125
      end
    end

## Цикличность

Если потребуется повторить что-то много раз, придётся указывать очень большие значения, такие как `1000.times do`. В этом случае, наверное, лучше попросить Sonic Pi повторять код до бесконечности (или, как минимум, до того момента, пока вы не нажмёте кнопку “Остановить”!). Давайте зациклим амен-брейк:

    loop do
      sample :loop_amen
      sleep sample_duration :loop_amen
    end

О циклах важно знать то, что они работают как чёрные дыры внутри кода. Как только исполнение кода попадает в цикл, оно не cможет покинуть его до тех пор, пока вы не остановите его. Код просто будет повторяться по кругу снова и снова вечно. Это значит, что вы никогда не услышите код, написанный после цикла. К примеру, тарелка после этого цикла никогда не прозвучит:

    loop do
      play 50
      sleep 1
    end
    sample :drum_cymbal_open

Теперь, пришла пора создать интересные структуры из вашего кода при помощи итераций и циклов!

# 5.3 - Условные выражения

Часто, помимо игры произвольных нот (см. предыдущую главу), вы также будете хотеть принимать произвольные решения и выполнять либо одну, либо другую ветку кода, в зависимости от результата. Например, вы можете решить случайным образом сыграть звук барабана или звук тарелки. Мы можем достичь этого при помощи выражения `if`.

## Подбрасывание монетки

Итак, давайте подбросим монетку: орел - играем на барабане, решка - бьём по тарелке. Это просто. Можно сымитировать это действие, используя функцию `one_in` (представлена в разделе, посвящённом случайности) с вероятностью один к двум: `one_in(2)`. Затем, мы можем использовать результат, чтобы выбрать один из двух участков кода: один - для звука барабана, другой - для тарелки:

    loop do
      if one_in(2)
        sample :drum_heavy_kick
      else
        sample :drum_cymbal_closed
      end
      sleep 0.5
    end

Отметим, что выражение `if` состоит из трёх частей:

Вопрос, на который нужно получить ответ Первый вариант исполняемого кода (выбирается, если ответ на вопрос “Да”) Второй вариант исполняемого кода (если ответ “Нет”)

Обычно, в программных языках ответ “Да” представлен термином `true` (истина), а `false` (ложь) означает “Нет”. То есть нам нужно задать вопрос, который даёт `true` или `false` ответ. Это именно то, что делает `one_in`.

Обратите внимание, что первый вариант действия размещается между `if` и `else`, а второй вариант находится между `else` и `end`. Как и в блоках do/end, допускается многострочный код. Например:

    loop do
      if one_in(2)
        sample :drum_heavy_kick
        sleep 0.5
      else
        sample :drum_cymbal_closed
        sleep 0.25
      end
    end

В этом случае мы добавляем задержку в течение разного количества времени в зависимости от сделанного выбора.

## Простое Условие

Иногда вам требуется условно выполнить всего лишь одну строчку кода. Это возможно, если написать `if` и сразу же ваш вопрос. Например:

    use_synth :dsaw
    loop do
      play 50, amp: 0.3, release: 2
      play 53, amp: 0.3, release: 2 if one_in(2)
      play 57, amp: 0.3, release: 2 if one_in(3)
      play 60, amp: 0.3, release: 2 if one_in(4)
      sleep 1.5
    end

Если запустить этот код, то каждый раз будут звучать разные аккорды, в которых вероятность появления каждой ноты будет различна.

# 5.4 - Потоки Выполнения

Итак, вы написали чумовую бас-партию и заводной ритм. Как сыграть обе эти части одновременно? Одно из решений - переплести их вместе вручную - играть небольшую чать баса, затем немного от ударных, потом еще бас… Однако, вскоре становится очень сложно даже думать о том, как разместить это все во времени, особенно если вы начнётк добавлять новые элементы.

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

## Бесконечные Циклы

Дабы не усложнять наш пример, представим, что это и есть крутой ритм и потрясающая бас-партия:

    loop do
      sample :drum_heavy_kick
      sleep 1
    end
    loop do
      use_synth :fm
      play 40, release: 0.2
      sleep 0.5
    end

Как мы уже обсуждали, циклы - это черные дыры в программе. Как только начинает выполняться цикл, выйти из него уже нельзя, не нажав кнопку “Остановить”. Как сыграть сразу оба цикла в одно и то же время? Надо сообщить Sonic Pi, что мы хотим выполнять что-то параллельно с остальной частью кода. Вот тут-то нам и придут на помощь потоки выполнения.

## Спасительные Потоки

    in_thread do
      loop do
        sample :drum_heavy_kick
        sleep 1
      end
    end
    loop do
      use_synth :fm
      play 40, release: 0.2
      sleep 0.5
    end

Обернув первый цикл в do/end блок типа `in_thread`, мы заставляем Sonic Pi выполнять содержимое блока do/end точно в то же самое время, когда начинается следующее выражение после блока do/end. В нашем примере таковым является второй цикл. Попробуйте, и вы услышите, как ударные и бас переплетаются вместе!

Теперь, что если мы хотим добавить синт поверх. Что-то типа:

    in_thread do
      loop do
        sample :drum_heavy_kick
        sleep 1
      end
    end
    loop do
      use_synth :fm
      play 40, release: 0.2
      sleep 0.5
    end
    loop do
      use_synth :zawa
      play 52, release: 2.5, phase: 2, amp: 0.5
      sleep 2
    end

Опять та же самая проблема. Первый цикл воспроизводится вместе со вторым из-за `in_thread`. Но третий цикл не достигается. То есть нам нужен ещё один поток:

    in_thread do
      loop do
        sample :drum_heavy_kick
        sleep 1
      end
    end
    in_thread do
      loop do
        use_synth :fm
        play 40, release: 0.2
        sleep 0.5
      end
    end
    loop do
      use_synth :zawa
      play 52, release: 2.5, phase: 2, amp: 0.5
      sleep 2
    end

## Течёт, Как Поток

Вас может это удивить, но при нажатии кнопки “Выполнить” также создаётся поток выполнения кода. Вот почему её многократное нажатие наслаивает звуки друг на друга. Запуски автоматически наслаивают звуки, потому что они сами являются потоками.

## Область Видимости

По мере овладевания секретами мастерства Sonic Pi вы узнаете, что потоки - это самые важные строительные блоки вашей музыки. Не последним их качеством является способность изолировать от других потоков то, что называется текущей установкой. Что это значит? Ну, когда вы переключаете синт при помощи `use_synth`, на самом деле вы изменяете синт в текущем потоке - ни в одном другом потоке он не изменится. Давайте посмотрим на это в действии:

    play 50
    sleep 1
    in_thread do
      use_synth :tb303
      play 50
    end
    sleep 1
    play 50

Обратите внимание, как звук в середине отличается от остальных. Команда `use_synth` применилась только к тому потоку, где она была выполнена, а не к окружающему главному потоку выполнения программы.

## Наследование

Когда вы создаёте новый поток, вызывая `in_thread`, то он автоматически наследует все текущие настройки из родительского потока. Проверим это:

    use_synth :tb303
    play 50
    sleep 1
    in_thread do
      play 55
    end

Заметили, что вторая нота воспроизводится на `:tb303`, несмотря на то, что это происходит в отдельном потоке? Любые регулировки, устанавливаемые различными `use_*` функциями, будут вести себя аналогично.

При создании, потоки наследуют все установки от своего родителя, но любые последующие изменения не имеют обратного эффекта.

## Именование Потоков

Наконец, мы можем называть наши потоки:

    in_thread(name: :bass) do
      loop do
        use_synth :prophet
        play chord(:e2, :m7).choose, release: 0.6
        sleep 0.5
      end
    end
    in_thread(name: :drums) do
      loop do
        sample :elec_snare
        sleep 1
      end
    end

Посмотрите на панель сообщений, когда этот код выполняется. Видите, как появляются сообщения, в которые включены имена потоков?

    [Run 36, Time 4.0, Thread :bass]
     |- synth :prophet, {release: 0.6, note: 47}

## Каждый Поток Со Своим Именем

Последнее, что вам нужно узнать об именованных потоках, это то, что только один поток с определённым именем может выполняться одновременно. Рассмотрим следующий код:

    in_thread do
      loop do
        sample :loop_amen
        sleep sample_duration :loop_amen
      end
    end

Скопируйте этот фрагмент в пустой буфер редактора и нажмите кнопку “Выполнить”. Нажмите её еще пару раз. Получилась какафония от того, что много повторений амен-брейка смешались вместе. Ладно, нажимайте “Остановить”.

Это то самое поведение, которое нам не раз уже доводилось наблюдать. Если нажимать кнопку “Выполнить”, то новый звук накладывается поверх уже играющего. Поэтому, если у вас есть цикл, и вы нажмёте кнопку “Выполнить” три раза, то получится три слоя циклов, звучащих вместе.

Но ситуация меняется с именованными потоками:

    in_thread(name: :amen) do
      loop do
        sample :loop_amen
        sleep sample_duration :loop_amen
      end
    end

Теперь попробуте понажимать кнопку “Выполнить” с этим кодом. Вы услышите только один цикл амен-брейк. В сообщениях вы также увидите:

    ==> Skipping thread creation: thread with name :amen already exists.

Sonic Pi сообщает вам, что поток с именем `:amen` уже существует, так что он не создаст ещё одного такого же.

Сейчас такое поведение может не показаться вам таким уж полезным. Но в дальнейшем вы ещё вспомните о нём, когда мы начнем лайвкодинг…

# 5.5 - Функции

Когда вы станете писать большое количество кода, вам потребуется способ организовать и структурировать элементы так, чтобы они выглядели более аккуратно, и их было бы проще понять. Функции - это очень мощный инструмент достижения этой цели. Они позволяют нам давать имена фрагментам кода. Посмотрим, как это работает.

## Определение Функций

    define :foo do
      play 50
      sleep 1
      play 55
      sleep 2
    end

Мы определили новую функцию, называющуюся `foo`. Мы сделали это при помощи нашего старого знакомого - блока do/end и магического слова `define`, за которым следует имя нашей функции. Необязательно было называть ее `foo`. Можно было придумать какое угодно название, к примеру `bar` или `baz`. Но, вообще-то, лучше всего, когда имя что-то означает, например `main_section` (главная секция) или `lead_riff` (солирующий рифф).

Не забывайте ставить двоеточие `:` перед именем функции, когда вы определяете её.

## Вызов Функций

Когда наша функция определена, мы можем вызвать её, просто написав её имя:

    define :foo do
      play 50
      sleep 1
      play 55
      sleep 0.5
    end
    foo
    sleep 1
    2.times do
      foo
    end

Можно использовать `foo` внутри повторяющихся блоков, а также везде, где мы могли бы использовать `play` или `sample`. Это даёт нам отличный способ самовыражения и создания новых обозначений в наших композициях.

## Функции Сохраняются Между Запусками

Пока что, всякий раз при нажатии кнопки “Выполнить”, Sonic Pi начинал с чистого листа. Ему не известно ничего, кроме того, что находится в буфере редактора. Нельзя ссылаться на код в другом буфере или другом потоке. Однако, функции меняют это. Когда вы определяете функцию, Sonic Pi запоминает ее. Попробуем. Удалите весь код в буфере и замените его вот на что:

    foo

Нажмите кнопку “Выполнить”, и убедитесь, что ваша функция играет. Куда же пропал код? Откуда Sonic Pi знал, что играть? Он просто вспомнил вашу функцию даже после её удаления из буфера. Он запомнил что вы напечатали. Это работает только с функциями, которые создаются при помощи `define` (и `defonce`)

## Функции С Параметрами

Вам, возможно, будет интересно узнать, что вашу функцию можно научить принимать аргументы, прямо как `rrand` принимает значения минимума и максимума. Посмотрим как это выглядит:

    define :my_player do |n|
      play n
    end
    my_player 80
    sleep 0.5
    my_player 90

Пример не очень интересный, но он показывает, что имеется в виду. Мы создали нашу собственную версию `play` с параметрами и назвали её `my_player`.

Параметры должны описываться после ключевого слова `do` блока `define`. Они должны быть окружены вертикальными стойками `|` и разделены запятыми `,`. Любые слова могут служить именами параметров.

Магия происходит внутри блока `define`. Там можно использовать имена параметров, как если бы они были настоящими значениями. В этом примере я проигрываю ноту `n`. Вы можете думать о параметрах, как о неких обещаниях о том, что при выполнении кода они будут заменены их значениями. Это достигается передачей параметра функции при её вызове. Чтобы сыграть ноту 80, я пишу `my_player 80`. Тогда внутри определения функции `n` меняется на 80, так что `play n` превращается в `play 80`. В следующий раз, когда я вызываю `my_player 90`, вместо `n` появляется 90, поэтому `play n` становится `play 90`.

Рассмотрим что-нибудь поинтереснее:

    define :chord_player do |root, repeats|
      repeats.times do
        play chord(root, :minor), release: 0.3
        sleep 0.5
      end
    end
    chord_player :e3, 2
    sleep 0.5
    chord_player :a3, 3
    chord_player :g3, 4
    sleep 0.5
    chord_player :e3, 3

Я использовал переменную `repeats`, как если бы она была числом в строке `repeats.times do`. Ещё я использовал `root` в качестве названия ноты для `play`.

Видите, как можно писать нечто очень выразительное и в то же время простое для чтения, если перенести большую часть логики в функцию!

# 5.6 - Переменные

Присвоение имён полезно для вашего кода. С Sonic Pi это очень просто. Вы пишете желаемое имя, знак равенства, а затем то, что нужно запомнить:

    sample_name = :loop_amen

В этом примере мы “запомнили” обозначение `:loop_amen` в переменной `sample_name`. Теперь мы можем пользоваться `sample_name` везде, где мы могли бы указать `:loop_amen`. Например:

    sample_name = :loop_amen
    sample sample_name

Есть три главных причины для использования переменных в Sonic Pi: присвоение значения, управление повторами и захват результатов операций.

## Присвоение Значения

Когда вы пишете код, вы говорите компьютеру сделать что-то. Пока компьютер это понимает - всё в порядке. Но всё же важно помнить, что код читает не только компьютер. Другие люди, возможно, захотят тоже прочесть его и попробовать разобраться, что в нём происходит. Скорее всего и вы сами будете читать и пытаться понять свой собственный код в будущем. Сейчас всё кажется очевидным, но для остальных, или же для вас самих в будущем, это может быть не так!

Одним из способов помочь другим понять, что делает ваш код, - это оставлять комментарии (как мы это видели в предыдущей главе). Ещё один способ - давать осмысленные имена переменным. Посмотрите на этот код:

    sleep 1.7533

Зачем указано число `1.7533`? Откуда оно взялось? Что оно означает? Теперь взгляните на этот пример:

    loop_amen_duration = 1.7533
    sleep loop_amen_duration

Вот теперь стало ясно, что значит `1.7533`. Это же продолжительность сэмпла `:loop_amen`! Конечно, вы могли бы заметить, почему бы просто не написать так:

    sleep sample_duration(:loop_amen)

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

## Управление Повторами

Часто вы видите много повторений в своем коде. Когда необходимо что-то поменять, то делать это приходится во многих местах. Посмотрите на следующее:

    sample :loop_amen
    sleep sample_duration(:loop_amen)
    sample :loop_amen, rate: 0.5
    sleep sample_duration(:loop_amen, rate: 0.5)
    sample :loop_amen
    sleep sample_duration(:loop_amen)

Много чего мы делаем с `:loop_amen`! Но что если мы захотим послушать как это будет звучать с другим замкнутым сэмплом, таким как `:loop_garzul`? Пришлось бы найти и заменить все `:loop_amen` на `:loop_garzul`. Этим можно заняться, если больше нечего делать. А как насчет живого выступления? Иногда время - это непозволительная роскошь. Особенно, если вы хотите, чтобы люди продолжали танцевать.

Ну, а если бы вы записали свой код так:

    sample_name = :loop_amen
    sample sample_name
    sleep sample_duration(sample_name)
    sample sample_name, rate: 0.5
    sleep sample_duration(sample_name, rate: 0.5)
    sample sample_name
    sleep sample_duration(sample_name)

Он делает совершенно то же самое (попробуйте сами). Зато тут есть возможность заменить строку `sample_name = :loop_amen` на `sample_name = :loop_garzul`, что приведёт к реальным изменениям во многих местах. Вот что даёт нам магия переменных.

## Захват Результатов

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

    sd = sample_duration(:loop_amen)

Теперь можно вставлять `sd` везде, где нам нужна длительность сэмпла `:loop_amen`.

Вероятно, ещё более важно то, что переменная разрешает нам сохранить результат вызова `play` или `sample`:

    s = play 50, release: 8

Мы захватили и запомнили `s` как переменную, которая позволяет управлять синтом, пока он играет:

    s = play 50, release: 8
    sleep 2
    control s, note: 62

В следующей главе мы рассмотрим подробнее управление синтами.

## Переменные

Whilst variables are great for giving things names and capturing the results of things, it is important to know that they should typically only be used locally within a thread. For example, don’t do this:

    a = (ring 6, 5, 4, 3, 2, 1)
    live_loop :shuffled do
      a = a.shuffle
      sleep 0.5
    end
    live_loop :sorted do
      a = a.sort
      sleep 0.5
      puts "sorted: ", a
    end

In the above example we assign a ring of numbers to a variable `a` and then used it within two separate `live_loop`s. In the first live loop every `0.5`s we sort the ring (to `(ring 1, 2, 3, 4, 5, 6)`) and then print it out to the log. If you run the code, you’ll find that the printed list is not always sorted!. This may surprise you - especially that sometimes the list is printed as sorted, and sometimes it is not. This is called non-deterministic behaviour and is the result of a rather nasty problem called a race-condition. The problem is due to the fact that the second live loop is also manipulating the list (in this case shuffling it) and by the time the list is printed, sometimes it has just been sorted and sometimes it has just been shuffled. Both live loops are racing to do something different to the same variable and every time round a different loop ‘wins’.

There are two solutions to this. Firstly, don’t use the same variable in multiple live loops or threads. For example, the following code will always print a sorted list as each live loop has its own separate variable:

    live_loop :shuffled do
      a = (ring 6, 5, 4, 3, 2, 1)
      a = a.shuffle
      sleep 0.5
    end
    live_loop :sorted do
      a = (ring 6, 5, 4, 3, 2, 1)
      a = a.sort
      sleep 0.5
      puts "sorted: ", a
    end

However, sometimes we do want to share things across threads. For example, the current key, BPM, synth etc. In these cases, the solution is to use Sonic Pi’s special thread-safe state system via the fns `get` and `set`. This is discussed later on in section 10.

# 5.7 - Синхронизация Потоков

Когда у вас начнёт достаточно хорошо получаться лайвкодинг с большим количеством потоков, выполняющихся одновременно, вы, скорее всего, заметите, что очень легко допустить ошибку, которая может прервать поток. Ничего страшного в этом нет, так как поток может быть перезапущен простым нажатием кнопки “Выполнить”. Однако, после перезапуска потока он будет играть невпопад с другими.

## Унаследованное Время

Как мы обсуждали ранее, новые потоки, созданные при помощи `in_thread` наследуют все настройки от родительского потока. Они включают и текущую метку времени. Это означает, что потоки всегда синхронизированы друг с другом после одновременного их запуска.

Но, когда поток стартует отдельно от родительского, внутри него ведётся собственный отсчет времени, который вряд ли совпадёт с каким-либо из других активных потоков.

## Функции cue и sync

В Sonic Pi решением этой проблемы являются функции `cue` и `sync`.

`cue` позволяет нам отправлять сигнал пульса другим потокам. По умолчанию, другие потоки не слушают и пропускают эти сообщения. Однако, поток может легко заявить о своей заинтересованности, вызвав функцию `sync`.

Важно осознавать, что функция `sync` похожа на `sleep`, ведь она останавливает текущий поток, и тот некоторое время не выполняется. Для `sleep` время простоя указывается явно, но вызвав `sync`, вы не знаете сколько времени оно продлится, потому что `sync` ждёт следующий `cue` от другого потока. Это может случиться скоро, а может и нет.

Давайте выясним немного больше деталей:

    in_thread do
      loop do
        cue :tick
        sleep 1
      end
    end
    in_thread do
      loop do
        sync :tick
        sample :drum_heavy_kick
      end
    end

Здесь у нас есть два потока. Один работает как метроном. Он не играет никаких звуков, только отправляет `:tick` сигнал каждую долю такта. Второй поток синхронизуется с сообщениями `tick`. Когда он получает `:tick` сообщение, то наследует временную отметку потока, вызвавшего `cue`, и продолжает выполнение.

В результате мы будем слышать сэмпл `:drum_heavy_kick` в тот самый момент, когда другой поток отправляет `:tick` сигнал. Даже если два этих потока стартовали не одновременно, это всё равно будет происходить:

    in_thread do
      loop do
        cue :tick
        sleep 1
      end
    end
    sleep(0.3)
    in_thread do
      loop do
        sync :tick
        sample :drum_heavy_kick
      end
    end

Результатом вызова `sleep` будет расхождение второго потока с первым. Однако, так как мы используем `cue` и `sync`, то мы автоматически синхронизируем потоки и избегаем любых случайных временных сдвигов.

## Имена Сигналов

Для сигналов `cue` можно использовать любые названия, а не только `:tick`. Просто следите за тем, чтобы все остальные потоки вызывали `sync` с правильным именем. Иначе они остановятся навсегда (или, по крайней мере, пока вы не нажмёте кнопку “Остановить”).

Попробуем что-нибудь с несколькими названиями `cue`:

    in_thread do
      loop do
        cue [:foo, :bar, :baz].choose
        sleep 0.5
      end
    end
    in_thread do
      loop do
        sync :foo
        sample :elec_beep
      end
    end
    in_thread do
      loop do
        sync :bar
        sample :elec_flip
      end
    end
    in_thread do
      loop do
        sync :baz
        sample :elec_blup
      end
    end

Тут у нас есть цикл с функцией `cue`, отправляющей пульс. Случайным образом этот пульс может быть назван `:foo`, `:bar` или `:baz`. Ещё есть три цикла в потоках, которые синхронизируются с каждым из этих сигналов независимо и воспроизводят разные сэмплы. Чистый эффект от этого кода в том, что каждые полсекунды мы слышим звук, так как каждый из потоков `sync` случайным образом синхронизируется с потоком `cue` и проигрывает свой сэмпл.

Конечно же, код будет работать даже если расположить потоки в обратном порядке, поскольку потоки будут дожидаться следующего `cue`.

# 6 - Студийные Эффекты

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

Sonic Pi даёт очень простой, но вместе с тем очень мощный способ добавления эффектов. Можно даже строить цепочки из них (таким образом можно пропустить звук через дисторшн, потом эхо и в конце реверберацию) и настраивать каждый из них по отдельности при помощи регулировок (как синты и сэмплы). Можно даже менять параметры эффектов пока они используются. Так, к примеру, реверберация баса может усиливаться в течение трэка…

## Гитарные Педали

Не переживайте, если это кажется вам слишком сложным. Всё станет намного понятнее после того, как вы попробуете это сами. Но пока полезной аналогией будет служить гитарный эффект. Есть много видов гитарных эффектов. Одни добавляют реверберацию, другие искажение и так далее. Гитарист подключает свой инструмент к педали, например дисторшн, затем другим кабелем добавляет в цепь педаль реверберации. После этого выход реверберации соединяется с усилителем:

    Гитара -> Дисторшн -> Реверберация -> Усилитель

Это называется каскадом эффектов. И это поддерживается в Sonic Pi. Вдобавок, обычно на каждой педали есть ручки и ползунки для управления применяемым эффектом. В Sonic Pi есть то же самое. Представьте себе музыканта, который что-то играет, а кто-то другой управляет эффектами. Такой способ тоже реализован в Sonic Pi, но тут вместо кого-то другого вступает в дело компьютер.

Давайте исследовать эффекты!

# 6.1 - Добавление Эффектов

В этом разделе мы рассмотрим пару эффектов - реверберацию и эхо. Мы увидим, как их использовать, как настраивать и как строить из них цепочки.

Система эффектов Sonic Pi использует блоки. Так что, если ты еще не прочел главу 5.1, было бы неплохо её просмотреть и вернуться назад.

## Реверберация

Нужно написать специальный блок `with_fx :reverb`, если мы хотим использовать реверберацию. Примерно так:

    with_fx :reverb do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

Теперь запустите этот код, и вы услышите как он звучит с реверберацией. Неплохо, правда? Все что угодно будет звучать отлично с реверберацией.

Посмотрим, что произойдет, если поместить код вне блока do/end:

    with_fx :reverb do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end
    sleep 1
    play 55

Обратите внимание, как последний `play 55` играется без реверберации. Это происходит потому, что эта строка находится за пределами блока do/end, то есть она не пропускается через эффект.

Точно так же, если играть звуки перед блоком do/end, то и они не будут обрабатываться эффектом:

    play 55
    sleep 1
    with_fx :reverb do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end
    sleep 1
    play 55

## Эхо

Есть множество эффектов на выбор. Как насчет эхо?

    with_fx :echo do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

Одна из сильных сторон блоков эффектов Sonic Pi в том, что у них есть регулировки, похожие на те, что мы уже видели у `play` и `sample`. Например, рассмотрим забавный параметр `phase:`, который представляет собой длительность эхо в долях такта. Сделаем эхо помедленнее:

    with_fx :echo, phase: 0.5 do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

Или побыстрее:

    with_fx :echo, phase: 0.125 do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

Заставим эхо затихать дольше, установив время `decay:` на 8 долей такта:

    with_fx :echo, phase: 0.5, decay: 8 do
      play 50
      sleep 0.5
      sample :elec_plip
      sleep 0.5
      play 62
    end

## Вкладывание Эффектов

Блоки эффектов можно вкладывать друг в друга, что позволяет очень легко собирать из них каскады эффектов. Например, что если вы захотите пропустить некоторый код через эхо, а потом через реверберацию? Легко! Просто поместите один эффект внутри другого:

    with_fx :reverb do
      with_fx :echo, phase: 0.5, decay: 8 do
        play 50
        sleep 0.5
        sample :elec_blup
        sleep 0.5
        play 62
      end
    end

Представьте как звук вытекает изнутри наружу. Весь звук из внутреннего блока do/end (такой как `play 50`) вначале попадает в эффект эхо, а затем звук с эффектом эхо в свою очередь отправляется в эффект реверберации.

Можно создавать очень глубокие вложения, чтобы получать непредсказуемые результаты. Однако, имейте в виду, что эффекты требуют больших ресурсов. При вложении они работают в одно и то же время. Так что используйте эффекты разумно, особенно на платформах с низким количеством ресурсов (например Raspberry Pi).

## Исследование Эффектов

В Sonic Pi встроено большое количество эффектов на выбор. Чтобы увидеть доступные, щелкните мышью по FX в левом нижнем углу справочной системы. Вот некоторые из моих любимых:

wobble, reverb, echo, distortion, slicer

Теперь вы можете добавлять эффекты везде, где только захочется!

# 6.2 - Практика Использования Эффектов

Хотя снаружи они выглядят обманчиво просто, внутри эффекты устроены довольно сложно. Их простота часто побуждает людей злоупотреблять их использованием. Это вполне нормально, если у вас мощный компьютер. Но если, как и я, вы импровизируете на Raspberry Pi, то нужно быть аккуратным с нагрузкой. Иначе ритм может начать прерываться.

Рассмотрим следующий код:

    loop do
      with_fx :reverb do
        play 60, release: 0.1
        sleep 0.125
      end
    end

В этом примере мы играем ноту 60 с очень коротким временем затухания. То есть это очень короткая нота. Нам нужна реверберация, поэтому мы обернули её в блок reverb. Пока что все хорошо. За исключением…

Посмотрим, что делает код. Во-первых, у нас есть цикл `loop`. Это означает, что всё, что внутри него, повторяется бесконечно. Во-вторых, есть блок `with_fx`. Его роль в том, чтобы создавать новый эффект реверберации каждый раз, когда он выполняется. Как будто для каждого щипка гитарной струны включается собственная педаль реверберации. Здорово, что так можно делать, но это не всегда то, что нам нужно. Например, такой код будет трудно выполнять на Raspberry Pi. Создание эффекта реверберации и ожидание момента, когда он должен быть остановлен и удален, - обо всем позаботится за тебя блок `with_fx`. Но на это требуются ресурсы процессора, а они могут быть ограничены.

Как изменить код так, чтобы он больше походил на обычное подключение, где у нашего гитариста всего одна педаль реверберации, через которую и пропускаются все звуки? Легко:

    with_fx :reverb do
      loop do
        play 60, release: 0.1
        sleep 0.125
      end
    end

Мы помещаем наш цикл внутрь блока `with_fx`. Таким образом создается всего один единственный эффект для всех нот, извлекаемых в цикле. Этот вариант намного более эффективен, и Raspberry Pi с ним хорошо справится.

В качестве компромисса можно предложить использовать `with_fx` на протяжении нескольких повторений внутри цикла:

    loop do
      with_fx :reverb do
        16.times do
          play 60, release: 0.1
          sleep 0.125
        end
      end
    end

То есть новый эффект реверберации будет создаваться через каждые 16 нот.

This is such a common pattern that `with_fx` supports an opt to do exactly this but without having to write the `16.times` block:

    loop do
      with_fx :reverb, reps: 16 do
        play 60, release: 0.1
        sleep 0.125
      end
    end

Both the `reps: 16` and `16.times do` examples will behave identically. The `reps: 16` essentially repeats the code in the `do/end` block 16 times so you can use them both interchangeably and choose the one that feels best for you.

Помните, ошибок нет, есть только возможности. Однако, каждый из этих подходов даст разный звук и разные показатели производительности. Поэтому попрактикуйтесь, а затем использте тот способ, который звучит лучше всего для вас, и в то же время укладывается в ограничения быстродействия вашей платформы.

# 7 - Управление Звуком Во Время Воспроизведения

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

Вот бы было здорово, если бы вы могли менять параметры воспроизводящегося звука, как вы може подтягивать вибрирующую струну гитары, правда?

Вам повезло - этот раздел покажет, как это можно сделаеть в Sonic Pi.

# 7.1 - Управление Играющим Синтезатором

Раньше мы изучали только как включать звуки и добавлять эффекты. Однако, в Sonic Pi есть возможность управлять воспроизводимыми звуками. Этого можно достичь, сохранив ссылку на синт в переменной:

    s = play 60, release: 5

В этом примере мы создали локальную переменную среды выполнения `s`, которая представляет собой синт, играющий ноту 60. Обратите внимание, что она локальна для текущего контекста - нельзя получить к ней доступ из других контекстов, таких как функции.

После того, как у нас появилась `s`, мы можем управлять ей с помощью функции `control`:

    s = play 60, release: 5
    sleep 0.5
    control s, note: 65
    sleep 0.5
    control s, note: 67
    sleep 3
    control s, note: 72

Заметьте, что мы запускаем не четыре разных синта, а один и просто изменяем высоту звука в то время, как он продолжает играть.

Можно передавать функции `control` любые из стандартных настроек, то есть доступен контроль над такими параметрами, как `amp:`, `cutoff:` или `pan:`.

## Неконтролируемые Настройки

Некоторые регулировки нельзя менять после включения синта. Это относится ко всем параметрам ADSR-огибающей. Из документации в справочной системе можно узнать какие параметры разрешено менять, а какие нет. Если документация говорит Нельзя изменять после установки, это значит, что после запуска синта настройке нельзя задавать новое значение.

# 7.2 - Управление Эффектами

Также в Sonic Pi доступен контроль над эффектами, хотя он и достигается немного другим способом:

    with_fx :reverb do |r|
      play 50
      sleep 0.5
      control r, mix: 0.7
      play 55
      sleep 1
      control r, mix: 0.9
      sleep 1
      play 62
    end

Мы используем параметры блока do/end вместо переменных. Нам надо задать уникальное имя для выбранного эффекта, окружив его вертикальными чертами `|`. Затем мы можем ссылаться на него изнутри охватывающего блока do/end. Так же работают и параметризованные функции.

Пришла пора немного поуправлять синтами и эффектами!

# 7.3 - Плавные Настройки

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

Рассмотрим пример:

    s = play 60, release: 5
    sleep 0.5
    control s, note: 65
    sleep 0.5
    control s, note: 67
    sleep 3
    control s, note: 72

Вы можете слышать, как высота звука синта сразу же меняется, как только происходит вызов `control`. Однако, что если мы захотим, чтобы параметр менялся плавно. Поскольку мы управляем значением `note:`, то для добавления плавности надо задать параметр синтезатора `note_slide`:

    s = play 60, release: 5, note_slide: 1
    sleep 0.5
    control s, note: 65
    sleep 0.5
    control s, note: 67
    sleep 3
    control s, note: 72

Теперь мы слышим, как ноты подтягиваются в промежутках между вызовами `control`. Звучит неплохо, не так ли? Можно ускорить скольжение звука, если указать более короткий интервал времени, например `note_slide: 0.2`, или замедлить его, установив большее значение.

Для каждой настройки, которой можно управлять, есть соответствующий `_slide` параметр, с которым можно поиграть.

## Скольжение Сохраняется

Если вы задали значение `_slide` для играющего синтезатора, то оно запомнится и будет использоваться всякий раз, когда соответствующая настройка меняется. Чтобы прекратить плавное изменение звука, надо установить значение `_slide` в 0 перед следующим вызовом `control`.

## Плавные Эффекты

Можно делать плавное изменение эффектов:

    with_fx :wobble, phase: 1, phase_slide: 5 do |e|
      use_synth :dsaw
      play 50, release: 5
      control e, phase: 0.025
    end

Пришла пора добавить немного плавности к вашей музыке…

# 8 - Структуры Данных

Очень полезный инструмент в инструментарии программиста - это структуры данных.

Иногда вы, возможно, захотите определить и использовать несколько разных вещей. Например, вы можете посчитать полезным иметь последовательность нот, чтобы играть их одну за другой. Языки программирования имеют структуры данных, чтобы вы могли делать это.

Существует множество интересных и экзотических структур данных, доступных для программистов, и люди постоянно изобретают новые. Впрочем, пока что мы нуждаемся в рассмотрении одной очень простой структуры данных - списка.

Давайте рассмотрим его более подробно. Мы узнаем про его базовую форму, а так же как списки могут быть использованы для представления гамм и аккордов.

# 8.1 - Списки

В этом разделе мы рассмотрим очень полезную структуру данных - список. Мы очень кратко познакомились с ним ранее в разделе о рандомизации, тогда мы случайным образом выбирали ноты из списка, чтобы играть их:

    play choose([50, 55, 62])

В этом разделе мы также изучим использование списков для представления аккордов и гамм. Сначала давайте вспомним, как мы можем сыграть аккорд. Помните, что если мы не используем `sleep`, все звуки воспроизводятся одновременно:

    play 52
    play 55
    play 59

Давайте посмотрим на другой способ представления этого кода.

## Воспроизведение Списка

Один из вариантов - разместить все ноы в виде списка: `[52, 55, 59]`. Наша дружественная функция `play` достаточно умна, чтобы понимать, как играть список нот. Попробуйте это:

    play [52, 55, 59]

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

    play [52, 55, 59], amp: 0.3

Конечно, мы также можем использовать традиционные имена нот вместо номеров MIDI:

    play [:E3, :G3, :B3]

Теперь те из вас, кому повезло изучать теорию музыки, смогут подтвердить, что аккорд ми минор был сыгран в 3-й октаве.

## Доступ К Списку

Еще одной полезной особенностью списка является возможность получать оттуда информацию. Это может звучать немного странно, но это не сложнее чьей-либо просьбы открыть книгу на странице 23. Применительно к списку, говорят - “Какой элемент находится по индексу 23”? Единственная странность заключается в том, что в программировании индексы начинаются с 0, а не с 1.

Мы не считаем индекы списка 1, 2, 3… вместо этого мы считаем 0, 1, 2…

Давайте рассмотрим это чуть более подробно. Взгляните на этот список:

    [52, 55, 59]

Здесь нет ничего страшного. Теперь, какой второй элемент в этом списке? Конечно, это `55`. Это было легко. Давайте посмотрим, что нам ответит компьютер на аналогичный вопрос:

    puts [52, 55, 59][1]

Это выглядит немного странно, если вы никогда не видели ничего подобного раньше. Поверьте мне, это не очень сложно. Строка выше состоит из трёх частей: слово `puts`, наш список `[52, 55, 59]` и наш индекс `[1]`. Сначала мы говорим `puts` потому что хотим, чтобы Sonic Pi напечатал ответ для нас в журнал. Далее, мы даём ему наш список, и, наконец, наш индекс запрашивает второй элемент. Мы должны окружить индекс квадратными скобками и т.к. счёт начинается с `0`, индекс второго элемента это `1`. Посмотрите:

    # indexes:  0   1   2
               [52, 55, 59]

Попробуйте выполнить код `puts [52, 55, 59][1]` и вы увидите, что `55` появится в журнале. Измените индекс `1` на другой, попробуйте более длинные списки и подумайте, как вы сможете использовать список в своём следующем сочинении. Например, какие музыкальные структуры могут быть представлены в виде ряда чисел…

# 8.2 - Аккорды

Sonic Pi имеет встроенную поддержку названий аккордов, которая возвращает списки. Попробуйте сами:

    play chord(:E3, :minor)

Теперь мы действительно проникаем куда-то. Это выглядит намного симпатичнее, чем сырые списки (и это легче читать). А как на счёт других аккордов, Sonic Pi их поддерживает? Да, и много. Попробуйте некоторые из них:

`chord(:E3, :m7)` `chord(:E3, :minor)` `chord(:E3, :dim7)` `chord(:E3, :dom7)`

## Арпеджио

Мы можем легко превратить аккорды в арпеджио с функцией `play_pattern`:

    play_pattern chord(:E3, :m7)

Хорошо, но не очень весело - она играла очень медленно. `play_pattern` будет играть каждую ноту из списка, вызывая `sleep 1` после каждого вызова `play`. Мы можем использовать другую функцию - `play_pattern_timed`, чтобы устанавливать наше собственное время и повысить скорость:

    play_pattern_timed chord(:E3, :m7), 0.25

Мы можем также передавать разное время в виде списка, который будет рассматриваться как кольцо:

    play_pattern_timed chord(:E3, :m13), [0.25, 0.5]

Это эквивалентно:

    play 52
    sleep 0.25
    play 55
    sleep 0.5
    play 59
    sleep 0.25
    play 62
    sleep 0.5
    play 66
    sleep 0.25
    play 69
    sleep 0.5
    play 73

Что бы вы предпочли написать?

# 8.3 - Гаммы

Sonic Pi поддерживает широкий диапазон гамм. Как насчет сыграть мажорную гамму от ноты С3?

    play_pattern_timed scale(:c3, :major), 0.125, release: 0.1

Мы даже можем запросить больше октав:

    play_pattern_timed scale(:c3, :major, num_octaves: 3), 0.125, release: 0.1

Как насчёт пентатоники?

    play_pattern_timed scale(:c3, :major_pentatonic, num_octaves: 3), 0.125, release: 0.1

## Случайные Ноты

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

    use_synth :tb303
    loop do
      play choose(chord(:E3, :minor)), release: 0.3, cutoff: rrand(60, 120)
      sleep 0.25
    end

Попробуйте другие названия аккордов и диапазоны частот среза фильтра.

## Нахождение Аккордов И Гамм

Чтобы выяснить, какие гаммы и аккорды поддерживаются Sonic Pi, просто нажмите кнопку lang внизу слева от этого учебника и затем выберите аккорд или гамму в списке. Прокручивайте вниз информацию в главной панели, пока не увидите длинный список аккордов или гамм (в зависимости от того, что вы ищете).

Получайте удовольствие и помните: здесь нет ошибок, только возможности.

# 8.4 - Кольца

Интересной разновидностью списков являются кольца. Если вы раньше занимались программированием, то наверняка сталкивались с кольцевым буфером или кольцевым массивом. Здесь мы узнаем про кольцевой список - это быстро и просто.

В предыдущем разделе о списках мы видели, как можно извлечь из них элементы, используя механизм индексирования:

    puts [52, 55, 59][1]

Так, а что произойдет, если вы захотите извлечь индекс `100`? Там явно нет элемента с индексом 100, так как у нашего списка только три элемента. Поэтому Sonic Pi вернет вам `nil`, что означает “ничто”.

Однако, представьте, что у вас есть счётчик, который, подобно номеру текущего такта, постоянно увеличивается. Давайте создадим наш счётчик и наш список:

    counter = 0
    notes = [52, 55, 59]

Теперь мы можем использовать счётчик, чтобы получить доступ к нотам в нашем списке:

    puts notes[counter]

Здорово, мы получили `52`. Теперь давайте увеличим наш счётчик и получим другую ноту:

    counter = (inc counter)
    puts notes[counter]

Супер, теперь мы получили `55` и если мы сделаем так снова, получим `59`. Однако, если после этого мы увеличим счётчик ещё раз, мы выйдем за пределы нашего списка и получим `nil`. Но что, если нам нужно вернуться к началу списка и снова начинать извлекать элементы по кругу? Вот для этого и нужны кольца.

## Создание Колец

Мы можем создавать кольца одним из двух способов. Либо используем функцию `ring` с элементами кольца в качестве параметров:

    (ring 52, 55, 59)

Либо можем взять обычный список и преобразовать его в кольцо, передав ему `.ring` сообщение:

    [52, 55, 59].ring

## Индексирование Колец

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

    (ring 52, 55, 59)[0] #=> 52
    (ring 52, 55, 59)[1] #=> 55
    (ring 52, 55, 59)[2] #=> 59
    (ring 52, 55, 59)[3] #=> 52
    (ring 52, 55, 59)[-1] #=> 59

## Использование Колец

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

## Гаммы И Аккорды Есть Кольца

Полезно знать, что списки, возвращаемые `scale` и `chord` также являются кольцами и позволяют получить к ним доступ с помощью произвольных индексов.

## Конструкторы Колец

В дополнение к `ring` существует ряд других функций, которые будут создавать кольца для нас.

`range` предлагает вам указать начальную точку, конечную точку и размер шага. `bools` позволяет использовать `1` и `0`, чтобы кратко представлять логические переменные. `knit` позволяет связывать в последовательности повторяющиеся значения. `spread` создает кольцо логических значений с Евклидовым распределением.

Взгляните на их соответствующую документацию для получения дополнительной информации.

# 8.5 - Колцевые Связки

Помимо конструкторов, таких как `range` и `spread`, есть и другой способ создания новых колец - манипулирование существующими кольцами.

## Связянные Методы

Чтобы исследовать это, возьмём простое кольцо:

    (ring 10, 20, 30, 40, 50)

Что, если мы хотим перевернуть его задом наперёд? Тогда мы используем связанный метод `.reverse`, который разворачивает кольцо в обратную сторону:

    (ring 10, 20, 30, 40, 50).reverse  #=> (ring 50, 40, 30, 20, 10)

Так, а что, если мы захотим получить первые три элемента кольца?

    (ring 10, 20, 30, 40, 50).take(3)  #=> (ring 10, 20, 30)

И, наконец, что, если мы захотим перемешать элементы кольца?

    (ring 10, 20, 30, 40, 50).shuffle  #=> (ring 40, 30, 10, 50, 20)

## Множественные Связки

Это очень мощный способ создания новых колец. Однако, реальная мощь приходит, когда вы связываете несколько методов вместе.

Как на счёт перемешать кольцо, отбросить 1 элемент, а затем получить первые 3 элемента?

Давайте сделаем это в несколько этапов:

`(ring 10, 20, 30, 40, 50)` - наше исходное кольцо `(ring 10, 20, 30, 40, 50).shuffle` - перемешиваем - `(ring 40, 30, 10, 50, 20)` `(ring 10, 20, 30, 40, 50).shuffle.drop(1)` - отбрасываем 1 элемент - `(ring 30, 10, 50, 20)` `(ring 10, 20, 30, 40, 50).shuffle.drop(1).take(3)` - берём 3 первых элемента - `(ring 30, 10, 50)`

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

## Неизменяемость

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

## Доступные Связанные Методы

Вот список доступных для вас связанных методов:

`.reverse` - возвращает отсортированную в обратном порядке версию кольца `.sort` - возвращает отсортированную версию кольца `.shuffle` - возвращает отсортированную в случайном порядке версию кольца `.pick(3)` - returns a ring with the results of calling `.choose` 3 times `.pick` - similar to `.pick(3)` only the size defaults to the same as the original ring `.take(5)` - возвращает кольцо, содержащее первые 5 элементов исходного кольца `.drop(3)` - возвращает кольцо, содержащее все элементы исходного кольца, кроме первых 3 элементов `.butlast` - возвращает новое кольцо с отсутствующим последним элементом `.drop_last(3)` - возвращает новое кольцо с отсутствующими 3 последними элементами `.take_last(6)`- возвращает кольцо, содержащее последние 6 элементов исходного кольца `.stretch(2)` - повторяет каждый элемент кольца дважды `.repeat(3)` - повторяет всё кольцо 3 раза `.mirror` - добавляет кольцо к перевёрнутой версии себя `.reflect` - то же, что и `.mirror`, но не дублирует средний элемент `.scale(2)` - returns a new ring with all elements multiplied by 2 (assumes ring contains numbers only)

Конечно, связанные методы, принимающие числовые аргументы, могут принимать и другие числа! Так что не стесняйтесь вызывать `.drop(5)` вместо `.drop(3)`, если вы хотите отбросить первые 5 элементов кольца.

# 9 - Лайв-кодинг

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

В этом разделе мы рассмотрим основы превращения статического кода ваших сочинений в динамичное исполнение.

Держитесь за своё кресло…

# 9.1 - Лайв-кодинг

Теперь мы узнали достаточно, чтобы начать по-настоящему развлекаться. В этом разделе мы будем черпать из всех предыдущих разделов и узнаем, как вы сможете делать свои музыкальные композиции живыми и превращать их в выступления. Для этого нам понадобится 3 основных компонента:

Умение писать код, который создаёт звук - ПРОВЕРЬТЕ! Умение писать функции - ПРОВЕРЬТЕ! Умение использовать (именовать) потоки - ПРОВЕРЬТЕ!

Чудненько, давайте начнём. Будем вживую кодировать наши первые звуки. Начнем с простого. Сначала нам нужна функция, содержащая код, который мы хотим проиграть. Ещё мы хотим зациклить вызовы этой функции в отдельном потоке:

    define :my_loop do
      play 50
      sleep 1
    end
    in_thread(name: :looper) do
      loop do
        my_loop
      end
    end

Если это выглядит для вас довольно сложным, вернитесь и перечитайте разделы о функциях и потоках. Это не сложно, если раньше вы уже прокручивал эти вещи у себя в голове.

То, что мы здесь имеем - это определение функции, которая всего лишь играет ноту 50 и немного ждёт. Затем мы определили именованную нить, названную `:looper`, которая бесконечно выполняет цикл с функцией `my_loop`.

Если вы выполните этот код, то услышите ноту 50 повторяющуюся снова и снова…

## Изменяем Это

Итак, вот где начинается веселье. В то время, как код по-прежнему выполняется, изменим 50 на другое число, скажем, на 55, и снова нажмём кнопку “Выполнить”. Ого! Всё изменилось! Вживую!

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

Попробуйте изменить это снова - измените ноту, измените время сна. Как на счёт добавления инструкции `use_synth`? Например, измените код на:

    define :my_loop do
      use_synth :tb303
      play 50, release: 0.3
      sleep 0.25
    end

Сейчас это звучит довольно интересно, но мы можем оживить это ещё больше. Вместо того, чтобы играть одну и ту же ноту снова и снова, попробуем сыграть аккорд:

    define :my_loop do
      use_synth :tb303
      play chord(:e3, :minor), release: 0.3
      sleep 0.5
    end

Как на счёт воспроизведения случайных нот из аккорда:

    define :my_loop do
      use_synth :tb303
      play choose(chord(:e3, :minor)), release: 0.3
      sleep 0.25
    end

Или использования случайных значений частоты среза:

    define :my_loop do
      use_synth :tb303
      play choose(chord(:e3, :minor)), release: 0.2, cutoff: rrand(60, 130)
      sleep 0.25
    end

Наконец, добавим немного барабанов:

    define :my_loop do
      use_synth :tb303
      sample :drum_bass_hard, rate: rrand(0.5, 2)
      play choose(chord(:e3, :minor)), release: 0.2, cutoff: rrand(60, 130)
      sleep 0.25
    end

Теперь это становится увлекательным!

Однако, прежде чем вы начнёте живое кодирование с функциями и потоками, остановите то, что вы сейчас делаете, и прочтите следующий раздел `live_loop`, который изменит манеру вашего кодирования в Sonic Pi навсегда…

# 9.2 - Живые циклы

Окей, этот раздел учебника - настоящая жемчужина. Если вы решите прочесть только один раздел, это должен быть именно этот раздел. Если вы прочли предыдущий раздел - основы лайвкодинга, `live_loop` - это простой способ сделать всё то же самое, но без необходимости писать так много кода.

Если вы не читали предыдущий раздел, `live_loop` - это лучший способ поджемовать с Sonic Pi.

Давайте поиграем. Наберите следующее в новом буфере:

    live_loop :foo do
      play 60
      sleep 1
    end

Теперь нажмите кнопку “Выполнить”. Вы услышите базовый звуковой сигнал на каждую долю такта. Здесь нет ничего весёлого. Однако, пока не нажимайте “Остановить”. Измените `60` на `65` и нажмите “Выполнить” снова.

Ого! Тон изменился автоматически без пропуска доли. Это и есть лайвкодинг.

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

    live_loop :foo do
      use_synth :prophet
      play :e1, release: 8
      sleep 8
    end

Затем нажмите “Выполнить”.

Давайте добавим изменяющуюся частоту среза:

    live_loop :foo do
      use_synth :prophet
      play :e1, release: 8, cutoff: rrand(70, 130)
      sleep 8
    end

Нажмите “Выполнить” снова.

Добавьте какие-нибудь барабаны:

    live_loop :foo do
      sample :loop_garzul
      use_synth :prophet
      play :e1, release: 8, cutoff: rrand(70, 130)
      sleep 8
    end

Измените ноту с `e1` на `c1`:

    live_loop :foo do
      sample :loop_garzul
      use_synth :prophet
      play :c1, release: 8, cutoff: rrand(70, 130)
      sleep 8
    end

Теперь хватит слушать меня и начните играь сами! Веселись!

# 9.3 - Несколько Живых Циклов

Рассмотрим следующий живой цикл:

    live_loop :foo do
      play 50
      sleep 1
    end

Вы, наверное, заинтересовались, почему он называется `:foo`. Это имя имеет значение, поскольку оно показывает, что этот живой цикл отличается от всех других живых циклов.

Не может быть двух живых циклов, выполняющихся под одним именем.

Это значит, что если мы хотим иметь несколько одновременно выполняющихся циклов, нам просто нужно дать им разные имена:

    live_loop :foo do
      use_synth :prophet
      play :c1, release: 8, cutoff: rrand(70, 130)
      sleep 8
    end
    live_loop :bar do
      sample :bd_haus
      sleep 0.5
    end

Теперь можно обновлять и изменять каждый живой цикл отдельно и всё будет прекрасно работать.

## Синхронизация Живых Циклов

Есть один важный момент, который вы, наверное, уже заметили - все живые циклы автоматически работают с механизмом распарралеливания потоков, который мы исследовали ранее. Всякий раз, когда живой цикл начинает выполняться, он генерирует новое `cue` событие с названием цикла. Следовательно, мы можем `sync` эти сигналы, чтобы гарантировать нашим циклам синхронизацию без необходимости что-либо останавливать.

Рассмотрим этот плохо синхронизированный код:

    live_loop :foo do
      play :e4, release: 0.5
      sleep 0.4
    end
    live_loop :bar do
      sample :bd_haus
      sleep 1
    end

Давайте посмотрим, сможем ли мы исправить тайминг и синхронизировать его без остановки воспроизведения. Сначала исправим время сна в цикле `:foo` на что-то вроде `0.5`:

    live_loop :foo do
      play :e4, release: 0.5
      sleep 0.5
    end
    live_loop :bar do
      sample :bd_haus
      sleep 1
    end

Но мы ещё не совсем закончили, ведь вы заметили, что такты пока не выстроились правильно. Это происходит потому, что циклы не в фазе. Давайте исправим это, синхронизировав один цикл с другим:

    live_loop :foo do
      play :e4, release: 0.5
      sleep 0.5
    end
    live_loop :bar do
      sync :foo
      sample :bd_haus
      sleep 1
    end

Ого, теперь всё прекрасно синхронизируется по времени и всё это без остановки.

А теперь вперёд! Кодируйте вживую с живыми петлями!

# 9.4 - Тики

Однажды, кодируя вживую, вы, вероятно, найдёте себя делающими множество вещей с помощью циклов, основанных на кольцах. Вы будете помещать в кольца мелодии, ритмы, последовательности аккордов, тембральные изменения и т.д и т.п.

## Тики И Кольца

Sonic Pi предоставляет очень удобный инструмент для работы с кольцами внутри `live_loop`. Он называется системой тиков. В разделе о кольцах мы говорили о счётчике, который постоянно увеличиватся, подобно номеру текущего такта. Тик как раз и реализует эту идею. Давайте рассмотрим примеры:

    counter = 0
    live_loop :arp do
      play (scale :e3, :minor_pentatonic)[counter], release: 0.1
      counter += 1
      sleep 0.125
    end

Это эквивалентно:

    live_loop :arp do
      play (scale :e3, :minor_pentatonic).tick, release: 0.1
      sleep 0.125
    end

Здесь мы просто берём минорную пентатонику, построенную от e3, и перебираем каждый элемент кольца. Это делается путём добавления `.tick` в конец объявления гаммы. Тик является локальным для живого цикла, поэтому каждый живой цикл может иметь свой собственный, независимый тик:

    live_loop :arp do
      play (scale :e3, :minor_pentatonic).tick, release: 0.1
      sleep 0.125
    end
    live_loop :arp2 do
      use_synth :dsaw
      play (scale :e2, :minor_pentatonic, num_octaves: 3).tick, release: 0.25
      sleep 0.25
    end

## Функция tick

Вы также можете вызвать `tick` как стандартную функцию и использовать возвращаемое ею значение в качестве индекса:

    live_loop :arp do
      idx = tick
      play (scale :e3, :minor_pentatonic)[idx], release: 0.1
      sleep 0.125
    end

Однако, гораздо изящнее вызывать `.tick` в конце объявления кольцевого списка. Функция `tick` полезна, когда вы хотите сделать что-то необычное с величиной тика или, если нужно, использовать тики для чего-то отличного от индексирования в кольцах.

## Функция Look

Магическая особенность тика заключается в том, что он не только возвращает новый индекс (или элемент кольцевого списка по этому индексу), он также гарантирует, что в следующий раз, когда вы вызовете тик, вы получите следующее значение. Посмотрите примеры для функции `tick` в разделе “Язык” документации, чтобы узнать о различных способах работы с ней. Впрочем, сейчас необходимо отметить, что иногда вам захочется просто посмотреть на текущее значение тика и не увеличивать его. Это доступно с помощью Функции `look`. Вы можете вызвать `look` как стандартную функцию путем добавления `.look` в конец кольцевого списка.

## Именование Тиков

Наконец, иногда вам может потребоваться использовать более одного тика внутри живой петли. Это достигается путем предоставления вашему тику имени:

    live_loop :arp do
      play (scale :e3, :minor_pentatonic).tick(:foo), release: 0.1
      sleep (ring 0.125, 0.25).tick(:bar)
    end

Здесь мы используем два тика - один для игры нот, другой для времени сна. Так как они оба находятся в одной и той же живой петле, чтобы держать их раздельно, нам нужно дать им уникальные имена. Это тот же самое, что и именование `live_loop` - мы просто передаем функции аргумент с префиксом `:`. В примере выше мы назвали один тик `:foo` а другой `:bar`. Если мы хотим применить функцию `look` к одному из тиков, нам нужно передать имя тика функции `look`.

## Не Делайте Это Слишком Сложным

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

Взгляните на документацию для функции `tick`, там много полезных примеров. Счастливых тиков!

# 10 - Time State

Often it is useful to have information that is shared across multiple threads or live loops. For example, you might want to share a notion of the current key, BPM or even more abstract concepts such as the current ‘complexity’ (which you’d potentially interpret in different ways across different threads). We also don’t want to lose any of our existing determinism guarantees when doing this. In other words, we’d still like to be able to share code with others and know exactly what they’ll hear when they run it. At the end of Section 5.6 of this tutorial we briefly discussed why we should not use variables to share information across threads due to a loss of determinism (in turn due to race conditions).

Sonic Pi’s solution to the problem of easily working with global variables in a deterministic way is through a novel system it calls Time State. This might sound complex and difficult (in fact, in the UK, programming with multiple threads and shared memory is typically a university level subject). However, as you’ll see, just like playing your first note, Sonic Pi makes it incredibly simple to share state across threads whilst still keeping your programs thread-safe and deterministic..

Meet `get` and `set`…

# 10.1 - Set and Get

Sonic Pi has a global memory store called Time State. The two main things you do with it are to `set` information and `get` information. Let’s dive deeper…

## Set

To store information into the Time State we need two things:

the information we want to store, a unique name (key) for the information.

For example, we might want to store the number `3000` with the key `:intensity`. This is possible using the `set` function:

    set :intensity, 3000

We can use any name for our key. If information has already been stored with that key, our new `set` will override it:

    set :intensity, 1000
    set :intensity, 3000

In the above example, as we stored both numbers under the same key, the last call to `set` ‘wins’, so the number associated with `:intensity` will be `3000` as the first call to `set` is effectively overridden.

## Get

To fetch information from the Time State we just need the key we used to `set` it, which in our case is `:intensity`. We then just need to call `get[:intensity]` which we can see by printing out the result to the log:

    print get[:intensity] #=> prints 3000

Notice that calls to `get` can return information that was `set` in a previous run. Once a piece of information has been `set` it is available until either the information is overridden (just like we clobbered the `:intensity` value of `1000` to `3000` above) or Sonic Pi is closed.

## Потоки Выполнения

The main benefit of the Time State system is that it can be safely used across threads or live loops. For example, you could have one live loop setting information and another one getting it:

    rrand

The nice thing about using `get` and `set` across threads like this is that it will always produce the same result every time you hit run. Go on, try it. See if you get the following in your log:

    {run: 0, time: 0.0}
     └─ 125.72265625
    {run: 0, time: 0.5}
     └─ 125.72265625
    {run: 0, time: 1.0}
     └─ 76.26220703125
    {run: 0, time: 1.5}
     └─ 76.26220703125
    {run: 0, time: 2.0}
     └─ 114.93408203125
    {run: 0, time: 2.5}
     └─ 114.93408203125
    {run: 0, time: 3.0}
     └─ 75.6048583984375
    {run: 0, time: 3.5}
     └─ 75.6048583984375

Try running it a few times - see, it’s the same every time. This is what we call deterministic behaviour and it’s really very important when we want to share our music as code and know that the person playing the code is hearing exactly what we wanted them to hear (just like playing an MP3 or internet stream sounds the same for all listeners).

## A Simple Deterministic State System

rand

    ## An Example of Non-Deterministic Behaviour
    ## (due to race conditions caused by multiple
    ## live loops manipulating the same variable
    ## at the same time).
    ##
    ## If you run this code you'll notice
    ## that the list that's printed is
    ## not always sorted!
    a = (ring 6, 5, 4, 3, 2, 1)
    live_loop :shuffled do
      a = a.shuffle
      sleep 0.5
    end
    live_loop :sorted do
      a = a.sort
      sleep 0.5
      puts "sorted: ", a
    end

Let’s take a look at how this might look using `get` and `set`:

    ## An Example of Deterministic Behaviour
    ## (despite concurrent access of shared state)
    ## using Sonic Pi's new Time State system.
    ##
    ## When this code is executed, the list that's
    ## printed is always sorted!
    set :a, (ring 6, 5, 4, 3, 2, 1)
    live_loop :shuffled do
      set :a, get[:a].shuffle
      sleep 0.5
    end
    live_loop :sorted do
      set :a, get[:a].sort
      sleep 0.5
      puts "sorted: ", get[:a]
    end

Notice how this code is pretty much identical to the version using a variable before it. However when you run the code, it behaves as you would expect with any typical Sonic Pi code - it does the same thing every time in this case thanks to the Time State system.

Therefore, when sharing information across live loops and threads, use `get` and `set` instead of variables for deterministic, reproducible behaviour.

# 10.2 - Sync

Section 5.7 introduced the functions `cue` and `sync` when dealing with the issue of synchronising threads. What it didn’t explain was that it is the Time State system which provides this functionality. It just so happens that `set` is actually a variation of `cue` and is built on top of the same core functionality which is to insert information into the Time State system. Additionally, `sync` is also designed in such a way that it works seamlessly with Time State - any information that we plan to store in Time State we can sync on. In other words - we `sync` on events yet to be inserted into Time State.

## Waiting for Events

Let’s take a quick look at how to use `sync` to wait for new events to be added to Time State:

    sample :ambi_lunar_land

foo

Note that `sync` always waits for future events and that it will block the current thread waiting for a new event. Also, it will inherit the logical time of the thread which triggered it via `set` or `cue` so it may also be used to sync time.

## Passing values into the Future

foo

    sample :ambi_lunar_land

Note that values that are passed through `set` and `cue` must be thread safe - i.e. immutable rings, numbers, symbols or frozen strings. Sonic Pi will throw an error if the value you are attempting to store in the Time State is not valid.

# 10.3 - Pattern Matching

foo

## Match any path segment

Let’s assume we want to wait for the next event that has three path segments:

    sync "/*/*/*"

This will match any Time State event with exactly three path segments, regardless of their names. For example:

foo foo `cue "/eggs/beans/toast"` `cue "/moog/synths/rule"`

However, it will not match paths with fewer or more path segments. The following will not match:

foo foo `cue "/eggs"`

Each `*` means any content. So we could match paths with just one segment with `/*` or paths with five segments with `/*/*/*/*/*`

## Matching partial segments

foo

foo foo foo

However, it wouldn’t match the following:

foo foo foo

foo

## Matching Nested Path Segments

foo

foo foo foo foo

## Matching Single Letters

You can use the `?` character to match against a single char such as `"/?oo/bar/baz"` which will match:

foo `cue "/goo/bar/baz"` `cue "/too/bar/baz"` `cue "/woo/bar/baz"`

## Matching Multiple Words

foo

foo foo foo

## Matching Multiple Letters

foo

foo foo foo

foo

foo foo foo foo foo

## Combining Matchers

When calling `sync` or `get` you are free to combine matchers in any order you see fit to powerfully match any Time State event created by `cue` or `set`. Let’s look at a crazy example:

    sample :loop_amen

## OSC Pattern Matching

For those curious, these matching rules are based on the Open Sound Control pattern matching specification which is explained in detail here: http://opensoundcontrol.org/spec-1_0

# 11 - MIDI

Once you’ve mastered converting code to music, you might wonder - what’s next? Sometimes the constraints of working purely within Sonic Pi’s syntax and sound system can be exciting and put you into a new creative position. However, sometimes it is essential to break out of the code into the real world. We want two extra things:

To be able to convert actions in the real world into Sonic Pi events to code with To be able to use Sonic Pi’s strong timing model and semantics to control and manipulate objects in the real world

Luckily there’s a protocol that’s been around since the 80s that enables exactly this kind of interaction - MIDI. There’s an incredible number of external devices including keyboards, controllers, sequencers, and pro audio software that all support MIDI. We can use MIDI to receive data and also use it to send data.

Sonic Pi provides full support for the MIDI protocol enabling you to connect your live code to the real world. Let’s explore it further…

# 11.1 - MIDI In

In this section we will learn how to connect a MIDI controller to send events into Sonic Pi to control our synths and sounds. Go and grab a MIDI controller such as a keyboard or control surface and let’s get physical!

## Connecting a MIDI Controller

In order to get information from an external MIDI device into Sonic Pi we first need to connect it to our computer. Typically this will be via a USB connection, although older equipment will have a 5-pin DIN connector for which you’ll need hardware support for your computer (for example, some sound cards have MIDI DIN connectors). Once you’ve connected your device, launch Sonic Pi and take a look at the IO section of the Preferences panel. You should see your device listed there. If not, try hitting the ‘Reset MIDI’ button and see if it appears. If you’re still not seeing anything, the next thing to try is to consult your operating system’s MIDI config to see if it sees your device. Failing all that, feel free to ask questions in the public chat room: http://gitter.im/samaaron/sonic-pi

## Receiving MIDI Events

Once your device is connected, Sonic Pi will automatically receive events. You can see for yourself by manipulating your MIDI device and looking at the cue logger in the bottom right of the application window below the log (if this isn’t visible go to Preferences->Editor->Show & Hide and enable the ‘Show cue log’ tickbox). You’ll see a stream of events such as:

    /midi/nanokey2_keyboard/0/1/note_off  [55, 64]
    /midi/nanokey2_keyboard/0/1/note_on   [53, 102]
    /midi/nanokey2_keyboard/0/1/note_off  [57, 64]
    /midi/nanokey2_keyboard/0/1/note_off  [53, 64]
    /midi/nanokey2_keyboard/0/1/note_on   [57, 87]
    /midi/nanokey2_keyboard/0/1/note_on   [55, 81]
    /midi/nanokey2_keyboard/0/1/note_on   [53, 96]
    /midi/nanokey2_keyboard/0/1/note_off  [55, 64]

Once you can see a stream of messages like this, you’ve successfully connected your MIDI device. Congratulations, let’s see what we can do with it!

## MIDI Time State

These events are broken into two sections. Firstly there’s the name of the event such as `/midi/nanokey2_keyboard/0/1/note_on` and secondly there’s the values of the event such as `[18, 62]`. Interestingly, these are the two things we need to store information in Time State. Sonic Pi automatically inserts incoming MIDI events into Time State. This means you can `get` the latest MIDI value and also `sync` waiting for the next MIDI value using everything we learned in section 10 of this tutorial.

## Управление Эффектами

Now we’ve connected a MIDI device, seen its events in the cue log and discovered that our knowledge of Time State is all we need to work with the events, we can now start having fun. Let’s build a simple MIDI piano:

    live_loop :midi_piano do
      note, velocity = sync "/midi/nanokey2_keyboard/0/1/note_on"
      synth :piano, note: note
    end

There’s a few things going on in the code above including some issues. Firstly, we have a simple `live_loop` which will repeat forever running the code between the `do`/`end` block. This was introduced in Section 9.2. Secondly, we’re calling `sync` to wait for the next matching Time State event. We use a string representing the MIDI message we’re looking for (which is the same as was displayed in the cue logger). Notice that this long string is provided to you by Sonic Pi’s autocompletion system, so you don’t have to type it all out by hand. In the log we saw that there were two values for each MIDI note on event, so we assign the result to two separate variables `note` and `velocity`. Finally we trigger the `:piano` synth passing our note.

Now, you try it. Type in the code above, replace the sync key with a string matching your specific MIDI device and hit Run. Hey presto, you have a working piano! However, you’ll probably notice a couple of problems: firstly all the notes are the same volume regardless of how hard you hit the keyboard. This can be easily fixed by using the velocity MIDI value and converting it to an amplitude. Given that MIDI has a range of 0->127, to convert this number to a value between 0->1 we just need to divide it by 127:

    live_loop :midi_piano do
      note, velocity = sync "/midi/nanokey2_keyboard/0/1/note_on"
      synth :piano, note: note, amp: velocity / 127.0
    end

Update the code and hit Run again. Now the velocity of the keyboard is honoured. Next, let’s get rid of that pesky pause.

## Removing Latency

Before we can remove the pause, we need to know why it’s there. In order to keep all the synths and FX well-timed across a variety of differently capable CPUs, Sonic Pi schedules the audio in advance by 0.5s by default. (Note that this added latency can be configured via the fns `set_sched_ahead_time!` and `use_sched_ahead_time`). This 0.5s latency is being added to our `:piano` synth triggers as it is added to all synths triggered by Sonic Pi. Typically we really want this added latency as it means all synths will be well timed. However, this only makes sense for synths triggered by code using `play` and `sleep`. In this case, we’re actually triggering the `:piano` synth with our external MIDI device and therefore don’t want Sonic Pi to control the timing for us. We can turn off this latency with the command `use_real_time` which disables the latency for the current thread. This means you can use real time mode for live loops that have their timing controlled by `sync`ing with external devices, and keep the default latency for all other live loops. Let’s see:

    live_loop :midi_piano do
      use_real_time
      note, velocity = sync "/midi/nanokey2_keyboard/0/1/note_on"
      synth :piano, note: note, amp: velocity / 127.0
    end

Update your code to match the code above and hit Run again. Now we have a low latency piano with variable velocity coded in just 5 lines. Wasn’t that easy!

## Приступая К Работе

Finally, as our MIDI events are going straight into the Time State, we can also use the `get` fn to retrieve the last seen value. This doesn’t block the current thread and returns `nil` if there’s no value to be found (which you can override by passing a default value - see the docs for `get`). Remember that you can call `get` in any thread at any time to see the latest matching Time State value. You can even use `time_warp` to jump back in time and call `get` to see past events…

## Now You are in Control

choose

# 11.2 - MIDI Out

In addition to receiving MIDI events we can also send out MIDI events to trigger and control external hardware synths, keyboards and other devices. Sonic Pi provides a full set of fns for sending various MIDI messages such as:

Note on - `midi_note_on` Note off - `midi_note_off` Control change - `midi_cc` Pitch bend - `midi_pitch_bend` Clock ticks - `midi_clock_tick`

There are many other supported MIDI messages too - check out the API documentation for all the other fns that start with `midi_`.

## Connecting to a MIDI Device

In order to send a MIDI message to an external device, we must first have connected it. Check out the subsection ‘Connecting a MIDI Controller’ in section 11.1 for further details. Note that if you’re using USB, connecting to a device which you’re sending to (rather than receiving from) is the same procedure. However, if you’re using the classic DIN connectors, make sure you connect to the MIDI out port of your computer. You should see your MIDI device listed in the preferences pane.

## Sending MIDI events

The many `midi_*` fns work just like `play`, `sample` and `synth` in that they send a message at the current (logical) time. For example, to spread out calls to the `midi_*` fns you need to use `sleep` just like you did with `play`. Let’s take a look:

    midi_note_on :e3, 50

This will send a MIDI note on event to the connected MIDI device with velocity 50. (Note that Sonic Pi will automatically convert notes in the form `:e3` to their corresponding MIDI number such as 52 in this case.)

If your connected MIDI device is a synthesiser, you should be able to hear it playing a note. To disable it use `midi_note_off`:

    midi_note_off :e3

## Selecting a MIDI device

By default, Sonic Pi will send each MIDI message to all connected devices on all MIDI channels. This is to make it easy to work with a single connected device without having to configure anything. However, sometimes a MIDI device will treat MIDI channels in a special way (perhaps each note has a separate channel) and also you may wish to connect more than one MIDI device at the same time. In more complicated setups, you may wish to be more selective about which MIDI device receives which message(s) and on which channel.

We can specify which device to send to using the `port:` opt, using the device name as displayed in the preferences:

    midi_note_on :e3, port: "moog_minitaur"

We can also specify which channel to send to using the `channel:` opt (using a value in the range 1-16):

    midi_note_on :e3, channel: 3

Of course we can also specify both at the same time to send to a specific device on a specific channel:

    midi_note_on :e3, port: "moog_minitaur", channel: 5

## MIDI Studio

Finally, a really fun thing to do is to connect the audio output of your MIDI synthesiser to one of the audio inputs of your soundcard. You can then control your synth with code using the `midi_*` fns and also manipulate the audio using `live_audio` and FX:

    with_fx :reverb, room: 1 do
      live_audio :moog
    end
    live_loop :moog_trigger do
      use_real_time
      midi (octs :e1, 3).tick, sustain: 0.1
      sleep 0.125
    end

(The fn `midi` is available as a handy shortcut to sending both note on and note off events with a single command. Check out its documentation for further information).

# 12 - OSC

In addition to MIDI, another way to get information in and out of Sonic Pi is via the network using a simple protocol called OSC - Open Sound Control. This will let you send messages to and from external programs (both running on your computer and on external computers) which opens up the potential for control way beyond MIDI which has limitations due to its 1980s design.

For example, you could write a program in another programming language which sends and receives OSC (there are OSC libraries for pretty much every common language) and work directly with Sonic Pi. What you can use this for is only limited by your imagination.

# 12.1 - Receiving OSC

By default when Sonic Pi is launched it listens to port 4559 for incoming OSC messages from programs on the same computer. This means that without any configuration, you can send Sonic Pi an OSC message and it will be displayed in the cue log just like incoming MIDI messages. This also means that any incoming OSC message is also automatically added to the Time State which means you can also use `get` and `sync` to work with the incoming data - just like with MIDI and synchronising `live_loops` - see sections 5.7 and 10.2 to recap how this works.

## A Basic OSC Listener

Let’s build a basic OSC listener:

    foo

In this example we described an OSC path `"/osc/trigger/prophet"` which we’re syncing on. This can be any valid OSC path (all letters and numbers are supported and the `/` is used like in a URL to break up the path to multiple words). The `/osc` prefix is added by Sonic Pi to all incoming OSC messages, so we need to send an OSC message with the path `/trigger/prophet` for our `sync` to stop blocking and the prophet synth to be triggered.

## Sending OSC to Sonic Pi

We can send OSC to Sonic Pi from any programming language that has an OSC library. For example, if we’re sending OSC from Python we might do something like this:

    from pythonosc import osc_message_builder
    from pythonosc import udp_client
    sender = udp_client.SimpleUDPClient('127.0.0.1', 4559)
    sender.send_message('/trigger/prophet', [70, 100, 8])

Or, if we’re sending OSC from Clojure we might do something like this from the REPL:

    (use 'overtone.core)
    (def c (osc-client "127.0.0.1" 4559))
    (osc-send c "/trigger/prophet" 70 100 8)

## Receiving from External Machines

For security reasons, by default Sonic Pi does not let remote machines send it OSC messages. However, you can enable support for remote machines in Preferences->IO->Network->Receive Remote OSC Messages. Once you’ve enabled this, you can receive OSC messages from any computer on your network. Typically the sending machine will need to know your IP address (a unique identifier for your computer on your network - kind of like a phone number or an email address). You can discover the IP address of your computer by looking at the IO section of the preferences pane. (If your machine happens to have more than one IP address, hovering the mouse over the listed address will pop up with a list of all known addresses).

Note, some programs such as TouchOSC for iPhone and Android support sending OSC as a standard feature. So, once you’re listening to remote machines and know your IP address you can instantly start sending messages from apps like TouchOSC which enable you to build your own custom touch controls with sliders, buttons, dials etc. This can provide you with an enormous range of input options.

# 12.2 - Sending OSC

In addition to receiving OSC and working with it using Time State, we can also send out OSC messages in time with our music (just like we can send out MIDI messages in time with our music). We just need to know which IP address and port we’re sending to. Let’s give it a try:

    use_osc "localhost", 4559
    osc "/hello/world"

If you run the code above, you’ll notice that Sonic Pi is sending itself an OSC message! This is because we set the IP address to the current machine and the port to the default OSC in port. This is essentially the same as posting a letter to yourself - the OSC packet is created, leaves Sonic Pi, gets to the network stack of the operating system which then routes the packed back to Sonic Pi and then it’s received as a standard OSC message and is visible in the cue logger as the incoming message `"/osc/hello/world`. (Notice how Sonic Pi automatically prefixes all incoming OSC messages with `/osc`.)

## Sending OSC to other programs

Of course, sending OSC messages to ourselves may be fun but it’s not that useful. The real benefit starts when we send messages to other programs:

    use_osc "localhost", 123456
    osc "/hello/world"

In this case we’re assuming there’s another program on the same machine listening to port 123456. If there is, then it will receive a `"/hello/world` OSC message with which it can do what it wants.

If our program is running on another machine, we need to know its IP address which we use instead of `"localhost"`:

    use_osc "192.168.10.23", 123456
    osc "/hello/world"

Now we can send OSC messages to any device reachable to us via our local networks and even the internet!

# 13 - Multichannel Audio

So far, in terms of sound production, we’ve explored triggering synths and recorded sounds via the fns `play`, `synth` and `sample`. These have then generated audio which has played through our stereo speaker system. However, many computers also have the ability to input sound, perhaps through a microphone, in addition to the ability to send sound out to more than two speakers. Often, this capability is made possible through the use of an external sound card - these are available for all platforms. In this section of the tutorial we’ll take a look at how we can take advantage of these external sound cards and effortlessly work with multiple channels of audio in and out of Sonic Pi.

# 13.1 - Sound In

One simple (and perhaps familiar) way of accessing sound inputs is using our friend `synth` by specifying the `:sound_in` synth:

    synth :sound_in

This will operate just like any synth such as `synth :dsaw` with the exception that the audio generated will be read directly from the first input of your system’s sound card. On laptops, this is typically the built-in microphone, but if you have an external sound card, you can plug any audio input to the first input.

## Длительность

One thing you might notice is that just like `synth :dsaw` the `:sound_in` synth only lasts for 1 beat as it has a standard envelope. If you’d like to keep it open for a little longer, change the ADSR envelope settings. For example the following will keep the synth open for 8 beats before closing the connection:

    synth :sound_in, sustain: 8

## Добавление Эффектов

Of course, just like any normal synth, you can easily layer on effects with the FX block:

    with_fx :reverb do
      with_fx :distortion do
        synth :sound_in, sustain: 8
      end
    end

If you have plugged in a guitar to your first input, you should be able to hear it with distortion and reverb until the synth terminates as expected.

You are free to use the `:sound_in` synth as many times as you like concurrently (just like you would do with any normal synth). For example, the following will play two `:sound_in` synths at the same time - one through distortion and one through reverb:

    with_fx :distortion do
      synth :sound_in, sustain: 8
    end
    with_fx :reverb do
      synth :sound_in, sustain: 8
    end

## Множественные Связки

You can select which audio input you want to play with the `input:` opt. You can also specify a stereo input (two consecutive inputs) using the `:sound_in_stereo` synth. For example, if you have a sound card with at least three inputs, you can treat the first two as a stereo stream and add distortion and the third as a mono stream and add reverb with the following code:

    with_fx :distortion do
      synth :sound_in_stereo, sustain: 8, input: 1
    end
    with_fx :reverb do
      synth :sound_in, sustain: 8, input: 3
    end

## Potential Issues

However, although this is a useful technique, there are a couple of limitations to this approach. Firstly, it only works for a specific duration (due to it having an ADSR envelope) and secondly, there’s no way to switch the FX around once the synth has been triggered. Both of these things are typical requests when working with external audio feeds such as microphones, guitars and external synthesisers. We’ll therefore take a look at Sonic Pi’s solution to the problem of manipulating a (potentially) infinite stream of live audio input: `live_audio`.

# 13.2 - Лайв-кодинг

The `:sound_in` synth as described in the previous section provides a very flexible and familiar method for working with input audio. However, as also discussed it has a few issues when working with a single input of audio as a single instrument (such as a voice or guitar). By far the best approach to working with a single continuous stream of audio is to use `live_audio`.

## A Named Audio Input

`live_audio` shares a couple of core design constraints with `live_loop` (hence the similar name). Firstly it must have a unique name and secondly only one `live_audio` stream with that name may exist at any one time. Let’s take a look:

    foo

This code will act in a similar fashion to `synth :sound_in` with some key differences: it runs forever (until you explicitly stop it) and you can move it to new FX contexts dynamically.

## Working with FX

On initial triggering `live_audio` works exactly as you might expect it to work with FX. For example, to start a live audio stream with added reverb simply use a `:reverb` FX block:

    foo

However, given that `live_audio` runs forever (at least until you stop it) it would be pretty limiting if, like typical synths, the live audio was bound within the `:reverb` FX for its entire existence. Luckily this is not the case and it was designed to be easy to move between different FX. Let’s try it. Run the code above to hear live audio coming directly from the first input of your sound card. Note, if you’re using a laptop, this will typically be out of your built-in microphone, so it’s recommended to use headphones to stop feedback.

Now, whilst you’re still hearing the audio live from the sound card with reverb, change the code to the following:

    foo

Now, hit Run, and you’ll immediately hear the audio played through the echo FX and no longer through reverb. If you wanted them both, just edit the code again and hit Run:

    foo

foo

## Stopping live audio

Unlike standard synths, as `live_audio` has no envelope, it will continue running forever (even if you delete the code, just like a function is still defined in memory if you delete the code in the editor). To stop it, you need to use the `:stop` arg:

    foo

It can easily be restarted by calling it without the `:stop` arg again:

    foo

Additionally all running live audio synths are stopped when you hit the global Stop button (as with all other running synths and FX).

## Stereo input

With respect to audio channels, by default `live_audio` acts similarly to the `:sound_in` synth in that it takes a single mono input stream of audio and converts it to a stereo stream using the specified panning. However, just like `:sound_in_stereo` it’s also possible to tell `live_audio` to read two consecutive audio inputs and treat them as the left and right channels directly. This is achieved via the `:stereo` opt. For example, to treat input 2 as the left signal and input 3 as the right signal, you need to configure the `input:` opt to 2 and enable stereo mode as follows:

    foo

Note that once you have started a live audio stream in stereo mode, you cannot change it to mono without stopping and starting. Similarly, if you start it in the default mono mode, you can’t switch to stereo without starting and stopping the stream.

# 13.3 - Sound Out

So far in this section we’ve looked at how to get multiple streams of audio into Sonic Pi - either through the use of the `:sound_in` synth or via the powerful `live_audio` system. In addition to working with multiple streams of input audio, Sonic Pi can also output multiple streams of audio. This is achieved via the `:sound_out` FX.

## Output contexts

Let’s quickly recap on how Sonic Pi’s synths and FX output their audio to their current FX context. For example, consider the following:

    with_fx :reverb do    # C
      with_fx :echo do    # B
        sample :bd_haus   # A
      end
    end

The simplest way to understand what’s happening with the audio stream is to start at the innermost audio context and work our way out. In this case, the innermost context is labelled `A` and is the `:bd_haus` sample being triggered. The audio for this goes directly into its context which is `B` - the `:echo` FX. This then adds echo to the incoming audio and outputs it to its context which is `C` - the `:reverb` FX. This then adds reverb to the incoming audio and outputs to its context which is the top level - the left and right speakers (outputs 1 and 2 in your audio card). The audio flows outwards with a stereo signal all the way through.

## Sound Out FX

The above behaviour is true for all synths (including `live_audio`) and the majority of FX with the exception of `:sound_out`. The `:sound_out` FX does two things. Firstly it outputs its audio to its external context as described above. Secondly it also outputs its audio directly to an output on your sound card. Let’s take a look:

    with_fx :reverb do      # C
      with_fx :sound_out, output: 3 do # B
        sample :bd_haus     # A
      end
    end

In this example, our `:bd_haus` sample outputs its audio to its external context which is the `:sound_out` FX. This in turn outputs its audio to its external context the `:reverb` FX (as expected). However, it also outputs a mono mix to the 3rd output of the system’s soundcard. The audio generated within `:sound_out` therefore has two destinations - the `:reverb` FX and audio card output 3.

## Mono and Stereo out

choose

## Direct Out

As we have also seen, the default behaviour for `:sound_out` and `:sound_out_stereo` is to send the audio both to their external context (as is typical of all FX) and to the specified output on your soundcard. However, occasionally you may wish to only send to the output on your soundcard and not to the external context (and therefore not have any chance of the sound being mixed and sent to the standard output channels 1 and 2). This is possible by using the standard FX opt `amp:` which operates on the audio after the FX has been able to manipulate the audio:

    sample :loop_amen

In the above example, the `:loop_amen` sample is sent to its outer context, the `:sound_out` FX. This then sends a mono mix to audio card output 3 and then multiplies the audio by 0 which essentially silences it. It is this silenced signal which is then sent out to the `:sound_out`’s outer context which is the standard output. Therefore with this code, the default output channels will not receive any audio, and channel 3 will receive a mono mix of the amen drum break.

# - Заключение

На этом и завершается вводное руководство по Sonic Pi. Надеюсь, вы узнали что-нибудь по пути. Не волнуйтесь, если чувствуете, что не всё поняли, просто играйте и веселитесь, и всё придёт в своё время. Не стесняйтесь снова погрузиться в чтение этого учебника, когда у вас возникнут вопросы, которые могут быть раскрыты в одной из глав.

Если у вас есть вопросы, которые в учебнике освещены не были, то, пожалуйста, зайдите на Sonic Pi forums и задайте свой вопрос там. Вы обязательно найдёте там кого-нибудь доброжелательного и готового протянуть руку помощи.

Наконец, я также приглашаю вас более детально рассмотреть остальную документацию этой справочной системы. Есть ряд особенностей, которые не были охвачены в этом учебнике, но ожидают вашего открытия.

Так играйте, веселитесь, делитесь кодом, выступайте для своих друзей, показывайте свои экраны и помните:

Здесь нет ошибок, только возможности.

Sam Aaron

# - Статьи MagPi

В Приложении A собраны статьи о Sonic Pi, выходившие в журнале MagPi.

## Погружение В Тему

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

## Читать В MagPi

Вы можете прочесть эти статьи в великолепном, профессионально оформленном виде, бесплатно загрузив их в формате PDF из MagPi

## Предложить Тему

Если вы не находите интересующую вас тему в этих статьях - почему бы не предложить свою? Самый простой способ сделать это - твитнуть в @Sonic_Pi. Кто знает, возможно предложенная вами тема станет предметом следующей статьи!

# - Пять Главных Советов

## 1. Здесь Нет Ошибок

Самый главный урок в обучении работе с Sonic Pi заключается в том, что здесь действительно нет ошибок. Лучший способ узнать это - пробовать, пробовать и ещё раз пробовать. Перестаньте беспокоиться о том, звучит ли ваш код хорошо или нет, и начните экспериментировать с как можно большим количеством различных синтезаторов, нот, эффектов и параметров. Вы откроете для себя множество вещей, которые заставят вас смеяться, потому что они звучат просто ужасно, но некоторые - настоящие жемчужины, звучащие просто потрясающе. Просто отбросьте то, что не нравится, и продолжайте делать то, что делаете. Чем больше “ошибок” вы позволите себе совершить, тем быстрее вы научитесь и откроете ваш собственный уникальный звук.

## 2. Используйте Эффекты

Допустим, вы уже освоили основы создания звука в Sonic Pi с помощью `sample` и `play`. Что дальше? Знаете ли вы, что Sonic Pi поддерживает более 27 студийных эффектов для изменения звука вашего кода? Эффекты похожи на причудливые фильтры изображений в графических редакторах, за исключением того, что вместо размытия или замены чего-то цветного чёрно-белым, вы можете использовать в своём звуке такие вещи, как реверберация, искажения и эхо. Думайте об этом, как о подключении кабеля от вашей гитары к педали эффектов, которую вы выбрали, а затем к усилителью. К счастью, Sonic Pi делает использование эффектов очень простым и не требует никаких проводов! Всё что вам нужно сделать - это выбрать, какой именно фрагмент кода вы бы обработали эффектом, и обернуть его в FX код. Давайте рассмотрим пример. Скажем, у вас есть следующий код:

    sample :loop_garzul

    16.times do
      sample :bd_haus
      sleep 0.5
    end

Если вы хотите добавить эффект в `:loop_garzul` сэмпл, просто поместите его внутрь `with_fx` блока, как здесь:

    with_fx :flanger do
      sample :loop_garzul
    end

    16.times do
      sample :bd_haus
      sleep 0.5
    end

Теперь, если вы захотите добавить эффект к басовому барабану, оберните его `with_fx` тоже:

    with_fx :flanger do
      sample :loop_garzul
    end

    with_fx :echo do
      16.times do
        sample :bd_haus
        sleep 0.5
      end
    end

Помните, вы можете обернуть любой код в `with_fx`, и любые созданные звуки будут проходить через выбранный эффект.

## 3. Параметризируйте Ваши Синтезаторы

Для того, чтобы создать действительно уникальный кодированный звук, вы, вероятно, захотите узнать как модифицировать и контролировать синтезаторы и эффекты. Например, вы можете захотеть изменить длительность ноты, добавить больше реверберации, или изменить время между повторами эхо. К счастью, Sonic Pi даёт вам удивительный уровень контроля с помощью специальных штук, называемых параметры. Давайте окинем их беглым взглядом. Скопируйте этот код в свободный буфер и нажмите “Выполнить”:

    sample :guit_em9

О, прекрасный звук гитары! Теперь, давайте начнём играть с ним. Как насчёт изменения его скорости?

    sample :guit_em9, rate: 0.5

Эй, что это за `rate: 0.5` я добавил в конце? Это называется параметр. Все синтезаторы и эффекты в Sonic Pi поддерживают их, и их тут множество. Они также доступны и для эффектов. Попробуйте это:

    with_fx :flanger, feedback: 0.6 do
      sample :guit_em9
    end

Теперь, попробуйте увеличить обратную связь до 1, чтобы услышать какие-то сумасшедшие звуки! Читайте документацию для получения полной информации о всех многочисленных параметрах, доступных для вас.

## 4. Live Code

Лучший способ быстро экспериментировать и исследовать Sonic Pi - кодирование в реальном времени. Это позволяет вам начать выполнять какой-то код, постоянно изменяя и подправляя его в то время, как он звучит. Например, если вы не знаете, что делает с сэмплом параметр частоты среза фильтра, просто играйте его по кругу и экспериментируйте. Давайте пробовать! Скопируйте этот код в буфер вашего Sonic Pi:

    live_loop :experiment do
      sample :loop_amen, cutoff: 70
      sleep 1.75
    end

Теперь, нажмите “Выполнить” и вы будете слышать чуть приглушенный барабанный брейк. Измените значение `cutoff:` на `80` и нажмите “Выполнить” снова. Слышите разницу? Попробуйте `90`, `100`, `110`…

Как только вы зависните с `live_loop`, вы уже никогда не вернётесь обратно. Всякий раз, когда я делаю лайвкодинг концерт, я завишу от `live_loop` так, как ударник зависит от своих палочек. Для получения дополнительной информации о лайвкодинге, проверьте раздел 9, встроенного учебника.

## 5. Поток Случайных Нот

Наконец, ещё одна вещь, которую я люблю делать, это давать Sonic Pi сочинять за меня музыку. Действительно крутой способ сделать это - использовать рандомизацию. Это может показаться сложным, но на самом деле это не так. Давайте проверим. Скопируйте это в свободное рабочее пространство:

    live_loop :rand_surfer do
      use_synth :dsaw
      notes = (scale :e2, :minor_pentatonic, num_octaves: 2)
      16.times do
        play notes.choose, release: 0.1, cutoff: rrand(70, 120)
        sleep 0.125
      end
    end

Когда вы запустите это, вы услышите постоянный поток случайных нот гаммы `:Е2 :minor_pentatonic`, сыгранную `:dsaw` синтезатором. “Подожди, подожди! Это не мелодия”, слышу я ваш возглас! Ну, это первая часть магического трюка. Каждый раз, когда мы проходим круг цикла `live_loop`, мы можем сказать Sonic Pi сбросить случайный поток к известной начальной точке. Это как будто возвращаться во времени в ТАРДИС С ДОКТОРОМ к определённой точке во времени и пространстве. Давайте попробуем это - добавьте строку `use_random_seed 1` к `live_loop`:

    live_loop :rand_surfer do
      use_random_seed 1
      use_synth :dsaw
      notes = (scale :e2, :minor_pentatonic, num_octaves: 2)
      16.times do
        play notes.choose, release: 0.1, cutoff: rrand(70, 120)
        sleep 0.125
      end
    end

Теперь каждый раз, как цикл `live_loop` повторяется, случайный поток будет сброшен. Это значит, что он выбирает одни и те же 16 нот каждый раз. Мгновенная мелодия. Теперь это действительно захватывающий бит. Изменитьте значение отправной точки с `1` на другое число. Скажем, `4923`. Ого! Другая мелодия! Так, просто изменяя одну цифру (отправную точку), вы можете открыть столько мелодических комбинаций, сколько сможете себе представить! Это и есть магия кода.

# - Лайв-кодинг

Лазерные лучи прорезали дым так же глубоко, как сабвуфер прокачивал низами танцующие тела. В атмосфере царила пьянящая смесь синтезаторов и танца. Однако, что-то в этом ночном клубе было не так… Яркими красками над кабиной диджея светился футуристический текст, движущийся, танцующий, вспыхивающий. Но это не были фантастические визуальные эффекты, это была лишь проекция Sonic Pi, запущенного на Raspberry Pi. Обитатель кабины диджея не крутил дисков, он писал, редактировал и запускал код. В реальном времени. Это был лайвкодинг.

Это может звучать как притянутая за уши история из футуристичного ночного клуба, но кодирование музыки - это развивающийся тренд, часто называемый Лайвкодинг (http://toplap.org). Одним из новых направлений этого способа создания музыки является Алгорэйв (http://algorave.com) - мероприятие, где такие артисты как я, кодируют музыку для танцующих людей. Однако, вам не надо быть в ночном клубе, чтобы кодировать в реальном времени - с Sonic Pi v2.6+ вы можете делать это в любом месте, в которое сможете взять ваш Raspberry Pi и пару наушников или колонок. Как только вы дойдёте до конца этой статьи, вы будете программировать свой собственный бит и изменять его вживую. То, где вы окажетесь после этого, может быть ограничено только вашим воображением.

## Живой Цикл

Ключ к лайвкодингу с Sonic Pi - овладение циклами `live_loop`. Давайте посмотрим на один из них:

    live_loop :beats do
      sample :bd_haus
      sleep 0.5
    end

Есть 4 основные составляющие циклов `live_loop`. Первая - это имя. Наш `live_loop` называется `:beats`. Вы вольны называть свой `live_loop` так, как вам угодно. С ума сойти. Подойдите к этому творчески. Обычно я использую имена циклов, что-то говорящие о музыке, которую они делают. Вторая состовляющая - это слово `do`, которое отмечает, где цикл начинается. Третья состовляющая - слово `end`, которое отмечает, где цикл заканчивается, и, наконец, есть тело цикла `live_loop`, которое описывает, что цикл повторяет - это часть кода между `do` и `end`. В данном случае мы многократно воспроизводим сэмпл бас бочки и ждём пол тактовой доли. Это производит приятный ровный ритм. Скопируйте этот код в пустой Sonic Pi буфер и нажмите “Выполнить”. Бум, Бум, Бум!.

## Изменения На Лету

Итак, что такого особенного в цикле `live_loop`? Он отдалённо напоминает усовершенствованный цикл `loop`. Преимущество `live_loop` в том, что вы можете изменять его на лету. Это значит, что пока выполняется цикл, вы можете изменить то, что он делает. Это и есть секрет лайвкодинга с Sonic Pi. Давайте играть:

    live_loop :choral_drone do
      sample :ambi_choir, rate: 0.4
      sleep 1
    end

Теперь, нажмите кнопку “Выполнить” или `Alt-r`. Вы услышите великолепный звук хора. Теперь, пока он ещё играет, измените скорость с `0.4` на `0.38`. Нажмите “Выполнить” снова. Ого! Вы слышите, как хор сменил ноту? Измените скорость обратно на `0.4`, чтобы вернуться к тому, что было раньше. Теперь, снизьте скорость до `0.2`, потом до `0.19`, а затем обратно до `0.4`. Видите, как изменение на лету одного лишь параметра, даёт вам реальный контроль над музыкой? Теперь поиграйте со скоростью самостоятельно - выберите свои собственные значения. Попробуйте отрицательные числа, попробуйте очень маленькие и очень большие числа. Повеселитесь!

## Сон Важен

Один из самых важных аспектов цикла `live_loop` в том, что в нём должна быть задержка. Рассмотрим следующий код:

    live_loop :infinite_impossibilities do
      sample :ambi_choir
    end

Если вы попробуете запустить этот код, вы сразу увидите жалобу Sonic Pi на то, что в `live_loop` нет `sleep`. Это ругается система безопасности! Воспользуйтесь моментом, чтобы подумать о том, что этот код просит сделать компьютер. Правильно, он просит компьютер играть бесконечное количество хоровых сэмплов за нулевое время. Без системы безопасности бедный компьютер будет пытаться сделать это, что приведёт к аварии. Поэтому помните, ваш `live_loop` должен содержать `sleep`.

## Сочетание Звуков

Музыка полна вещей, происходящих одновременно. Барабаны звучат в то же самое время, что и бас, вокал, гитары… В информатике это называется параллелизм и Sonic Pi обеспечивает нам удивительно простой способ играть разные вещи в одно и то же время. Просто используйте больше, чем один `live_loop`!

    live_loop :beats do
      sample :bd_tek
      with_fx :echo, phase: 0.125, mix: 0.4 do
        sample  :drum_cymbal_soft, sustain: 0, release: 0.1
        sleep 0.5
      end
    end

    live_loop :bass do
      use_synth :tb303
      synth :tb303, note: :e1, release: 4, cutoff: 120, cutoff_attack: 1
      sleep 4
    end

Здесь у нас есть два цикла `live_loop`, один цикл делает быстрый ритм, а другой - медленный сумасшедший басовый звук.

Одна из особенностей использования нескольких циклов `live_loop` состоит в том, что каждый из них обладает своим собственным независимым временем. Это значит, что с помощью этого легко создавать интересные полиритмические структуры и даже поиграть с фазировкой в стиле Стива Рейха (Steve Reich). Зацени:

    # Steve Reich's Piano Phase

    notes = (ring :E4, :Fs4, :B4, :Cs5, :D5, :Fs4, :E4, :Cs5, :B4, :Fs4, :D5, :Cs5)

    live_loop :slow do
      play notes.tick, release: 0.1
      sleep 0.3
    end

    live_loop :faster do
      play notes.tick, release: 0.1
      sleep 0.295
    end

## Соединим Всё Вместе

Каждую из этих статей мы будем заканчивать примером в виде фрагмента музыкального произведения, который вырисовывается из всех представленных в статье идей. Прочтите этот код и посмотрите, сможете ли вы понять, что он делает. Затем скопируйте его в свежий буфер Sonic Pi, нажмите “Выполнить” и послушайте, как он самом деле звучит. Наконец, измените одно из чисел или закомментируйте/раскомментируйте какие-нибудь строки. Посмотрите, сможете ли вы использовать этот пример в качестве отправной точки для нового выступления, и самое главное, веселитесь! До встречи в следующий раз…

    with_fx :reverb, room: 1 do
      live_loop :time do
        synth :prophet, release: 8, note: :e1, cutoff: 90, amp: 3
        sleep 8
      end
    end

    live_loop :machine do
      sample :loop_garzul, rate: 0.5, finish: 0.25
      sample :loop_industrial, beat_stretch: 4, amp: 1
      sleep 4
    end

    live_loop :kik do
      sample :bd_haus, amp: 2
      sleep 0.5
    end

    with_fx :echo do
      live_loop :vortex do
        # use_random_seed 800
        notes = (scale :e3, :minor_pentatonic, num_octaves: 3)
        16.times do
          play notes.choose, release: 0.1, amp: 1.5
          sleep 0.125
        end
      end
    end

# - Кодирование ритмов

Одной из самых захватывающих и разрушающих технических разработок современной музыки, стало изобретение сэмплеров. Это были коробки, которые позволяли записывать в них любой звук, а затем воспроизводить и управлять этим звуком множеством различных способов. Например, можно взять старую записать, найти барабанное соло (или брэйк), записать его в свой сэмплер и воспроизводить на половинной скорости, обеспечивая основу для своих собственных ритмов. Так зарождался ранний хип-хоп, и сегодня практически невозможно найти электронную музыку, в составе которой нет сэмплов в том или ином виде. Использование сэмплов - это действительно отличный способ легко внедрять новые интересные элементы в ваше лайвкодинг выступление.

Так где же можно получить сэмплер? Ну, у вас уже есть один - это ваш Raspberry Pi! Идущее в комплекте приложение для лайвкодинга Sonic Pi имеет чрезвычайно мощный сэмплер, встроенный в его ядро. Давайте с ним поиграем!

## Амен-брейк

Один из самых узнаваемых сэмплов классических барабанных брейков называется Амен-брейк. Он впервые прозвучал в 1969 году в песне “Аминь, Брат”, исполнителя “Winstons”, как часть барабанного брейка. Тем не менее, когда он был обнаружен ранними хип-хоп музыкантами в 80-х годах и начал использоваться в сэмплерах, он стал активно внедряться и в другие стили, такие как драм-эн-бэйс, брейкбит, хардкор, техно и брейк-кор.

Я уверен, что вы будете взволнованы, узнав, что он также входит в состав Sonic Pi. Очистите буфер и поместите в него следующий код:

    sample :loop_amen

Нажмите Выполнить и бум! Вы слушаете один из самых влиятельных барабанных брейков в истории танцевальной музыки. Однако, этот сэмпл не стал бы известен, будучи сыгран сам по себе, он был выбран для того, чтобы стать петлёй.

## Растяжение Ритмов

Давайте зациклим амен-брейк, используя наш старый добрый цикл `live_loop`, представленный в прошлом выпуске этого журнала:

    live_loop :amen_break do
      sample :loop_amen
      sleep 2
    end

ОК, мы его зациклили, но при каждом повторе есть неприятная пауза. Это потому, что мы сказали Sonic Pi ждать `2` тактовые доли, а с учётом того, что по умолчанию BPM (ударов в минуту) равно 60, сэмпл `:loop_amen` длится только `1.753` удара. Поэтому мы имеем тишину `2 - 1.753 = 0.247` удара. Даже не смотря на то, что она довольно короткая, она всё равно заметна.

Чтобы устранить эту проблему, мы можем воспользоваться параметром `beat_stretch:`, чтобы сказать Sonic Pi растянуть (или сжать) сэмпл согласно установленнму количеству ударов.

Функции Sonic Pi `sample` и `synth` дают вам контроль через необязательные параметры, такие как `amp:`, `cutoff:` и `release:`. Однако, термин “необязательный параметр” - это слишком длинное название, поэтому для простоты будем называть их просто параметры.

    live_loop :amen_break do
      sample :loop_amen, beat_stretch: 2
      sleep 2
    end

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

## Играем Со Временем

ОК, но что, если мы хотим изменить стиль на олдскульный хип-хоп или брейк-кор? Один из простейших способов сделать это - играть со временем - или, другими словами, сдвинуть темп. В Sonic Pi это супер просто - добавьте `use_bpm` в живой цикл:

    live_loop :amen_break do
      use_bpm 30
      sample :loop_amen, beat_stretch: 2
      sleep 2
    end

Пока вы будете читать рэп под этот медленный ритм, обратите внимание, что мы до сих пор ждём 2 удара, и хотя наш BPM 30, всё продолжает звучать пропорционально. Параметр `beat_stretch` работает с текущим BPM, чтобы быть уверенным, что всё будет работать исправно.

Теперь самое интересное. Пока цикл всё ещё исполняется, изменми `30` в строке `use_bpm 30` на`50`. Ого, всё ускорилось, но продолжает звучать равномерно во времени! Попытайтесь разогнаться ещё быстрее - до 80, до 120, или, сойдите с ума, и дайте 200!

## Фильтрация

Теперь, когда мы можем зацикливать сэмплы в реальном времени, давайте взглянем на некоторые из самых забавных параметров, предоставляемых сэмплером. Первый - `cutoff:`, который контролирует частоту среза фильтра. По умолчанию эта возможность отключена, но вы можете легко её включить:

    live_loop :amen_break do
      use_bpm 50
      sample :loop_amen, beat_stretch: 2, cutoff: 70
      sleep 2
    end

Давайте изменим параметр `cutoff:`. Например, увеличте его до 100, нажмите Выполнить и ждите, пока круг цикла завершится, чтобы услышать изменения в звуке. Обратите внимание, что низкие значения, такие как 50, дают сочный звук и басы, а высокие значения, типа 100 и 120, дают более полное звучание и больше высокочастотных составляющих. Это происходит потому, что параметр `cutoff:` срубает высокочастотную область звука так же, как газонокосилка срезает верхнюю часть травы. Параметр `cutoff:` определяет сколько “травы” оставлять.

## Нарезка

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

    live_loop :amen_break do
      use_bpm 50
      with_fx :slicer, phase: 0.25, wave: 0, mix: 1 do
        sample :loop_amen, beat_stretch: 2, cutoff: 100
      end
      sleep 2
    end

Обратите внимание, как звук стал более упругим (вы можете услышать оригинальное звучание сэмпла без эффекта, установив параметр `mix:` в `0`.) Теперь поиграйтесь с параметром `phase:`. Это размер (в ударах) нарезки. Меньшее значение, такое как `0.125`, нарежет сэмпл более короткими кусками и в большем количестве, чем значение `0.5`, при котором нарезка будет реже и толще. Обратите внимание, что удвоения значений `phase`, как правило, всегда звучат хорошо. Наконец, измените параметр `wave:`, выбрав из 0, 1 или 2, и послушайте, как меняется звук. Это три разные формы волны. 0 - это пилообразная волна, (резко начинается, плавно затухает), 1 - прямоугольная волна (резко начинается, резко обрывается), и 2 - треугольная волна (плавно нарастает, плавно затухает).

## Соединим Всё Вместе

Наконец, давайте вернёмся назад во времени, и вновь посетим раннюю Бристольскую драм-эн-бэйс сцену. Не волнуйтесь о том, что всё это значит, просто введите этот код в пустой буфер, нажмите “Выполнить”, и начинайте лайвкодинг. Изменяйте значения параметров и подумайте, где бы вы смогли применить это. Пожалуйста, поделитесь тем, что у вас получилось! Увидимся в следующий раз…

    use_bpm 100

    live_loop :amen_break do
      p = [0.125, 0.25, 0.5].choose
      with_fx :slicer, phase: p, wave: 0, mix: rrand(0.7, 1) do
        r = [1, 1, 1, -1].choose
        sample :loop_amen, beat_stretch: 2, rate: r, amp: 2
      end
      sleep 2
    end

    live_loop :bass_drum do
      sample :bd_haus, cutoff: 70, amp: 1.5
      sleep 0.5
    end

    live_loop :landing do
      bass_line = (knit :e1, 3, [:c1, :c2].choose, 1)
      with_fx :slicer, phase: [0.25, 0.5].choose, invert_wave: 1, wave: 0 do
        s = synth :square, note: bass_line.tick, sustain: 4, cutoff: 60
        control s, cutoff_slide: 4, cutoff: 120
      end
      sleep 4
    end

# - Синтезаторные Риффы

Какой бы звук вы не использовали, солирующий синтезатор всегда играет главную роль в любом электронном треке. В статье из прошлого номера мы рассматривали, как кодировать барабанные биты. В этой статье мы узнаем, как кодировать три основных компонента синтезаторных риффов - тембр, мелодию и ритм.

Итак, подключите ваш Paspberry Pi, откройте Sonic Pi версии v2.6+ и давайте пошумим!

## Тембральные Возможности

Неотъемлемой частью любого синтезаторного риффа является его тембр. Мы можем изменять тембр в Sonic Pi двумя способами - выбирая различные синты для резкой смены тембра, и изменяя различные синтовые параметры для более тонкой настройки. Мы также можем использовать эффекты, но об этом в другой раз…

Давайте создадим простой живой цикл, в котором будет постоянно изменяться текущий синт:

    live_loop :timbre do
      use_synth (ring :tb303, :blade, :prophet, :saw, :beep, :tri).tick
      play :e2, attack: 0, release: 0.5, cutoff: 100
      sleep 0.5
    end

Взгляните на код. Мы просто перебираем по кругу элементы кольцевого списка, содержащего имена синтов (цикл переключает синт на следующий в списке снова и снова). Мы передаём имена этих синтов функции `use_synth`, которая и переключает текущий синтезатор цикла `live_loop`. Ещё мы играем ноту `:Е2` (ми второй октавы), со временем затухания 0.5 удара (пол секунды с ВРМ по умолчанию 60) и с параметром `cutoff:`, равным 100.

Слышите, разные синтезаторы звучат совершенно по-разному, хотя играют одну и ту же ноту? Теперь давайте поэкспериментируем. Измените время затухания на большее или меньшее значение. Изменяйте оба параметра - `attack:` и `release:`, чтобы посмотреть, как сильно разные их значения изменяют звук. Наконец, измените параметр `cutoff:`, чтобы услышать, что разные значения среза фильтра также радикально изменяют тембр синта (значения между 60 и 130 обычно звучат хорошо). Посмотрите, сколько разнообразных звуков можно создать, изменяя всего лишь несколько параметров. Как только вы это освоите, откройте вкладку “Синтезаторы” справочной системы, и взгляните на полный список синтезаторов и их параметров, чтобы увидеть, какую мощь вы держите в руках.

## Тембр

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

## Мелодическая Структура

Ещё одним важным аспектом нашего солирующего синтезатора является выбор нот, которые он будет играть. Если у вас уже есть хорошая мелодическая идея, то вы можете просто создать кольцо с вашими нотами, и воспроизводить его по кругу:

    live_loop :riff do
      use_synth :prophet
      riff = (ring :e3, :e3, :r, :g3, :r, :r, :r, :a3)
      play riff.tick, release: 0.5, cutoff: 80
      sleep 0.25
    end

Здесь мы поместили нашу мелодию в кольцевой список, содержащий ноты, такие как `:е3` и паузы, обозначенные `:r`. Затем, мы использовали `.tick`, чтобы получить повторяющийся рифф.

## Автомелодия

Не всегда бывает легко придумать хороший рифф с нуля. Вместо этого, иногда проще сказать Sonic Pi играть случайный рифф, и выбрать тот, который понравится вам больше всего. Для этого нам необходимо объединить три вещи: кольца, рандомизацю и отправную точку (зерно) рандомизаци. Взгляните на пример:

    live_loop :random_riff do
      use_synth :dsaw
      use_random_seed 3
      notes = (scale :e3, :minor_pentatonic).shuffle
      play notes.tick, release: 0.25, cutoff: 80
      sleep 0.25
    end

Здесь происходит несколько вещей - давайте рассмотрим их по очереди. Во-первых, мы указли, что используем зерно рандомизаци 3. Что это значит? Ну, смысл в том, что когда мы устанавливаем зерно, мы можем предсказать, какой будет рандомизаця в следующий раз. Той же самой, что и в тот раз, когда мы устанавливали зерно в 3! Ещё одна вещь, которую полезно знать, что перемешивание нот кольца будет произведено тем же способом. В примере выше, мы, по сути, вызываем “третье перемешивание” из стандартного списка перемешиваний, который остаётся неизменным всякий раз, когда мы устанавливаем зерно в то же значение перед перемешиванием. Наконец, мы просто вызываем по кругу наши перемешанные ноты, чтобы получить рифф.

Вот где начинается веселье. Если мы меняем значение зерно рандомизаци на другое, скажем 3000, мы получаем совершенно другое перемешивание нот. Так что теперь очень легко исследовать новые мелодии. Просто выберите список нот, которые вы хотите перемешать (гаммы представляют собой отличную отправную точку), а затем выберите зерно рандомизаци, с которого вы хотите начать перемешивание. Если вам не нравится мелодия, просто измените одну из этих двух вещей и попробуйте снова. Повторяйте до тех пор, пока вам понравится то, что вы слышите!

## Псевдо Рандомизация

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

## Поиск Ритма

Ещё один важный аспект нашго риффа, это ритм - т.е. последовательность нот и пауз. Как мы видели раньше, мы можем использовать `:r` в наших кольцах, чтобы вставить паузу. Ещё один очень мощный способ - использовать методы колец, но о них мы поговорим в следующий раз. Сегодня мы будем использовать рандомизацию, чтобы помочь нам найти подходящий ритм. Вместо того, чтобы играть каждую ноту, мы можем играть ноту с заданной вероятностью. Давайте посмотрим:

    live_loop :random_riff do
      use_synth :dsaw
      use_random_seed 30
      notes = (scale :e3, :minor_pentatonic).shuffle
      16.times do
        play notes.tick, release: 0.2, cutoff: 90 if one_in(2)
        sleep 0.125
      end
    end

Очень полезно знать функцию `one_in`, которая возвращает нам `true` или `false` с заданной вероятностью. Здесь мы используем значение 2, поэтому в среднем один раз каждые два вызова, `one_in` возвратит `true`. Другими словами, она будет возвращать `true` в 50% случаев. Если использовать более высокие значения, `false`будет возвращаться чаще, добавляя в рифф больше пауз.

Заметим, что мы добавили повторы `16.times`. Это потому, что мы хотим сбрасывать наше зерно рандомизаци каждые 16 нот. Так наш ритм будет повторяться каждые 16 ударов. Это не влияет на перемешивание, т.к. оно выполняется сразу после того, как установлено зерно рандомизаци. Мы можем использовать разное количество повторов для изменения длины риффа. Попробуйте изменить 16 на 8 или даже на 4 или 3 и посмотрите, как это повлияет на ритм.

## Соединим Всё Вместе

ОК, теперь давайте совместим всё, чему мы научились, в один финальный пример. Увидимся в следующий раз!

    live_loop :random_riff do
      #  uncomment to bring in:
      #  synth :blade, note: :e4, release: 4, cutoff: 100, amp: 1.5
      use_synth :dsaw
      use_random_seed 43
      notes = (scale :e3, :minor_pentatonic, num_octaves: 2).shuffle.take(8)
      8.times do
        play notes.tick, release: rand(0.5), cutoff: rrand(60, 130) if one_in(2)
        sleep 0.125
      end
    end

    live_loop :drums do
      use_random_seed 500
      16.times do
        sample :bd_haus, rate: 2, cutoff: 110 if rand < 0.35
        sleep 0.125
      end
    end

    live_loop :bd do
      sample :bd_haus, cutoff: 100, amp: 3
      sleep 0.5
    end

# - Кислотный Бас

Невозможно исследовать историю электронной танцевальной музыки, и не заметить огромного влияния крошечного синтезатора Roland TB-303. Это секретный ингридиент оригинального кислотного баса. Классическое визжание и чавканье басовых риффов TB-303 можно услышать в ранней чикагской хаус сцене благодаря таким музыкантам, как Plastikman, Squarepusher и Aphex Twin.

Интересно, что инженеры Roland никогда не предполагали, что TB-303 будет использоваться в танцевальной музыке. Он изначально создавался для гитаристов. Они расчитывали, что гитаристы будут программировать TB-303 играть басовые линии в джемах. К сожалению, существовал ряд проблем: они были немного неудобными для программирования, не очень хорошо звучали в качестве замены бас-гитары и были довольно дорогими. Решив сократить убытки, Roland прекратили их выпуск после продажи 10 000 экземпляров, и после нескольких лет лежания на полках, эи синтезаторы можно было найти только в магазинах “секонд хенд”. Эти одинокие, отвергнутые TB-303 ждали, когда их обнаружит новое поколение экспериментаторов, которые начали применять их способом, который в Roland и представить не могли, создавая новые сумасшедшие звуки. Так зародился эйсид хаус.

Хотя получить на руки оригинал TB-303 не так уж и просто, вам будет приятно узнать, что вы можете превратить ваш Raspberry Pi в один из них, используя мощь Sonic Pi. Узрите свет Sonic Pi, забросив этот код в пустой буфер и нажав “Выполнить”:

    use_synth :tb303
    play :e1

Мгновенный кислотный бас! Давайте с ним поиграем…

# - Изменяем Бас

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

    use_synth :tb303
    live_loop :squelch do
      n = (ring :e1, :e2, :e3).tick
      play n, release: 0.125, cutoff: 100, res: 0.8, wave: 0
      sleep 0.125
    end

Для начала рассмотрим код построчно:

В первой строке мы задаём синтезатор по умолчанию `tb303` с помощью функции `use_synth`. Во второй строке мы создаем живой цикл `:squelch`, который будет просто повторяться снова и снова. Третья строка - та, где мы создаём наш рифф - кольцо нот (ми в октавах 1, 2 и 3), которые мы извлекаем по кругу с помощью `.tick`. Мы определяем `n` для представления текущей ноты в риффе. Знак равенства присваивает значение справа, имени, находящемуся слева. Это значение будет отличаться каждый круг цикла. Первый круг `n` будет иметь значение `:е1`. Второй круг - `:е2`, затем `:е3`, потом снова `:е1` и так круг за кругом. Четвёртая строка - место, где мы включаем наш `:tb303`. У нас здесь есть несколько интересных параметров: `release:`, `cutoff:`, `res:` и `wave:`, которые мы обсудим чуть позже. В пятой строке появляется `sleep` - мы просим цикл замыкать круг каждые `0.125` удара, или 8 раз в секунду с BPM по умолчанию 60. Строка шесть - это `end` живого цикла. Мы просто говорим Sonic Pi, что здесь конец живого цикла.

В то время, как вы всё ещё пытаетесь понять, что здесь происходит, поместите этот код в пустой буфер, и нажмите кнопку “Выполнить”. Вы должны услышать `:tb303` в действии. Теперь пора начинать лайвкодинг.

В то время, как цикл исполняется, измените параметр `cutoff:` на `110`. Затем нажмите кнопку “Выполнить” снова. Вы должны услышать, что звук стал немного жёстче и более “хлюпающим”. Наберите `120` и нажмите “Выполнить”. Затем `130`. Слушайте, как более высокие значения делают звук более пронзительным и интенсивным. Наконец, понизьте значение до `80`, если захотите отдохнуть. Затем повторите это столько раз, сколько захотите. Не волнуйтесь, я всё ещё буду здесь…

Ещё один параметр, с которым стоит поиграть, это `res:`. Он контролирует уровень резонанса фильтра. Для кислотных басовых партий характерен высокий резонанс. В настоящее время наш `res:` установлен в `0.8`. Попробуйте изменить его на `0.85`, затем на `0.9`, и наконец, на `0.95`. Вы можете обнаружить, что предельные значения `cutoff:`, такие как `110` или выше, помагают легче услышать различия. Наконец, сойдите с ума и установите `0.999`, чтобы получить действительно безумный звук. С этим значением `res:` вы слышите так много резонанса, что он начинает звучать сам по себе!

Наконец, для резкого изменения тембра попробуйте изменить параметр `wawe:` на `1`. Это выбор формы волны исходного генератора. Значение по умолчанию - `0` - пилообразная волна, `1` - прямоугольная волна, и `2` - треугольная форма волны.

Конечно, пробуйте разные риффы, изменяя ноты в кольце, или же выбирая ноты из гамм, или аккордов. Веселитесь с вашим первым кислотным басовым синтезатором.

# - Деконструирование TB-303

Конструкция оригинальных TB-303 на самом деле довольно проста. Как вы можете видеть из следующей диаграммы, главных составляющих всего 4.

Первой является волновой герератор - сырая основа звука. В этом примере у нас прямоугольная волна. Дальше идёт генератор амплитудной огибающей, который контролирует амплитуду прямоугольной волны во времени. Он доступен в Sonic Pi в виде параметров `attack:`, `decay:`, `sustain:` и `release:`. Для получения более подробной информации об этих параметрах читайте раздел 2.4 “Длительность с помощью огибающих” встроенного учебника. Затем, мы пропускаем наш амплитудно модулированный сигнал через резонансный низкочастотный фильтр. Это срубает высокочастотную составляющую, а также добавляет этот приятный резонансный эффект. Теперь начинается самое весёлое. Значение среза этого фильтра может управляться своей собственной огибающей! Это значит, что мы имеем удивительный контроль над тембром звука, играя двумя этими огибающими. Давайте приступим:

    use_synth :tb303
    with_fx :reverb, room: 1 do
      live_loop :space_scanner do
        play :e1, cutoff: 100, release: 7, attack: 1, cutoff_attack: 4, cutoff_release: 4
        sleep 8
      end
    end

В синтезаторе `:tb303`, для каждого стандартного параметра огибающей есть `cutoff_` эквивалент. Так, для изменения времени атаки фильтра, мы можем использовать параметр `cutoff_attack:`. Скопируйте приведенный выше код в пустой буфер, и нажмите “Выполнить”. Вы услышите безумный плавающий звук. Теперь поиграем. Попробуйте изменять время `cutoff_attack:` на `1`, а затем на `0.5`. Потом попробуйте `8`.

Заметьте, что я пропустил звук через `:reverb` эффект для создания дополнительной атмосферы - попробуйте другие эффекты, чтобы посмотреть, как это работает!

# - Соединим Всё Вместе

Наконец, ниже расположен фрагмент кода, который я сочинил, используя идеи этой статьи. Скопируйте его в свой буфер, послушайте, а потом начните лайвкодинг, внося свои собственные изменения. Посмотрим, какие безумные звуки вы сможете создать с помощью этого! Увидимся в следующий раз…

    use_synth :tb303
    use_debug false

    with_fx :reverb, room: 0.8 do
      live_loop :space_scanner do
        with_fx :slicer, phase: 0.25, amp: 1.5 do
          co = (line 70, 130, steps: 8).tick
          play :e1, cutoff: co, release: 7, attack: 1, cutoff_attack: 4, cutoff_release: 4
          sleep 8
        end
      end

      live_loop :squelch do
        use_random_seed 3000
        16.times do
          n = (ring :e1, :e2, :e3).tick
          play n, release: 0.125, cutoff: rrand(70, 130), res: 0.9, wave: 1, amp: 0.8
          sleep 0.125
        end
      end
    end

# - Музыкальный Minecraft

Привет, и с возвращением! В предыдущих упражнениях мы сосредотачивались исключительно на музыкальных возможностях Sonic Pi - (превращая ваш Raspberry Pi в готовый к выступлению музыкальный инструмент). К этому моменту мы научились:

Кодировать в реальном времени, Создавать различные ритмы, Генерировать мощные солирующие синты, Воссоздавать знаменитые кислотные басы TB-303.

Однако, есть ещё множество аспектов создания музыки, которые нужно показать вам (что я и сделаю в будущем). Но в этом месяце мы рассмотрим особенность Sonic Pi, о наличии которой вы, наверное, даже и не подозревали: управлять Minecraft.

# - Привет, Мир Minecraft

ОК, давайте начнём. Подключите ваш Raspberry Pi, запустите Minecraft Pi и создайте новый мир. Теперь запустите Sonic Pi, измените размеры окон и разместите их так, чтобы вы могли видеть одновременно и Minecraft Pi, и Sonic Pi.

В пустом буфере наберите следующее:

    mc_message "Hello Minecraft from Sonic Pi!"

Теперь, нажмите “Выполнить”. Бум! Ваше сообщение появилось в Minecraft! Ну как, это было легко? Теперь, прекратите на мгновение чтение этой статьи и поиграйте с вашими собственными сообщениями. Веселитесь!

# - Sonic Телепортатор

Теперь давайте исследовать мир Minecraft. Стандартный вариант - дотянуться до мыши и клавиатуры и начать перемещаться в мире Minecraft. Это работает, но это довольно медленно и скучно. Было бы гораздо интереснее, если бы у нас было что-то вроде телепортатора. Благодаря Sonic Pi, мы имеем один. Попробуйте это:

    mc_teleport 80, 40, 100

Боже мой! Это был долгий путь вверх. Если вы не находились в режиме полёта, то должны были упасть обратно на землю. Если вы дважды нажмёте пробел для входа в режим полёта и телепортируетесь снова, вы останетесь висеть на том месте, куда вы в телепортировались.

Итак, что же означают эти цифры? У нас есть три числа, которые описывают координаты места, куда мы хотим переместиться. Мы даём каждой цифре имя - х, y и z:

x - как далеко от левого края (в нашем примере - 80) y - как высоко (в нашем примере - 40) z - как далеко вглубь мира (в нашем примере - 100)

Выбирая различные значения для x, y и z, мы можем телепортироваться куда угодно. Попробуйте! Выбирайте различные цифры и смотрите, где вы окажетесь. Если экран стал чёрным, это произошло потому, что вы телепортировали себя под землю или внутрь скалы. Просто выбирите значение `y` выше, чтобы оказаться снова над землёй. Продолжайте исследования, пока не найдёте место, которое вам понравится…

Используя эти идеи, построим телепортатор, который издаёт весёлый звук телепортации, пока переносит нас сквозь мир Minecraft:

    mc_message "Preparing to teleport...."
    sample :ambi_lunar_land, rate: -1
    sleep 1
    mc_message "3"
    sleep 1
    mc_message "2"
    sleep 1
    mc_message "1"
    sleep 1
    mc_teleport 90, 20, 10
    mc_message "Whoooosh!"

# - Магические Блоки

Сейчас, когда вы нашли хорошее место, начнём строительство. Вы могли бы делать то, к чему привыкли, и начать яростно кликать мышкой, распологая блоки под курсором. Или вы могли бы использовать магию Sonic Pi. Попробуйте это:

    x, y, z = mc_location
    mc_set_block :melon, x, y + 5, z

Теперь посмотри вверх! В небе дынный блок! Найдите минутку, чтобы посмотреть на код. Что он делает? На первой строке мы определили текущее местоположение как переменные x, y и z. Они соответствуют нашим координатам, описанным выше. Мы использовали эти координаты в функции `mc_set_block`, которая поместила блок, который мы выбрали, по указанным координатам. Чтобы указать сделать что-то выше в небе, нам просто нужно увеличить значение `y`, вот почему мы добавляем 5 к нему. Сделаем длинный след из этих блоков:

    live_loop :melon_trail do
      x, y, z = mc_location
      mc_set_block :melon, x, y-1, z
      sleep 0.125
    end

Теперь переключитесь на Minecraft, убедитесь что вы находитесь в режиме полёта (двойное нажатие на пробел, если нет) и летайте по всему миру. Обернитесь, чтобы увидеть длинный след дынных блоков! Посмотрите, какие извилистые структуры вы можете сделать в небе.

# - Лайвкодинг Minecraft

Тем из вас, кто следит за этими статьями в течение последних нескольких месяцев, наверное снесёт крышу к этому моменту. След дынных блоков это очень здорово, но самая захватывающая часть предыдущего пример заключается в том, что вы можете использовать `live_loop` с Minecraft! Для тех, кто не знает, цикл `live_loop` в Sonic Pi - особая магическая способность, которой нет других языках программирования. Он позволяет запускать несколько циклов в одно и то же время и изменять их, пока они выполняются. Они невероятно мощные и удивительно весёлые. Я использую `live_loop`, чтобы исполнять музыку в ночных клубах с Sonic Pi - диджеи используют диски, а я циклы `live_loop`:-) Тем не менее, сегодня мы собираемся кодировать в реальном времени и музыку, и Minecraft.

Давайте начнём. Запустите приведенный выше код и начните делать свой дынный след снова. Теперь, не останавливая код, просто измените `:melon` на `:brick` и нажмите “Выполнить”. Вуаля, вы теперь делаете кирпичную дорогу. Это было просто! Добавим немного музыки в это? Легко. Попробуйте это:

    live_loop :bass_trail
      tick
      x, y, z = mc_location
      b = (ring :melon, :brick, :glass).look
      mc_set_block b, x, y -1, z
      note = (ring :e1, :e2, :e3).look
      use_synth :tb303
      play note, release: 0.1, cutoff: 70
      sleep 0.125
    end

Теперь, пока это играет, начнём вносить изменения в наш код. Измените тип блока. Попробуйте `:water`, `:grass` или другой ваш любимый тип блока. Также, попробуйте изменть значение отсечки фильтра с `70` до `80` и затем до `100`. Разве это не весело?

# - Соединим Всё Вместе

Давайте объединим всё, что мы видели до сих пор, с небольшой дополнительной магией. Совместим наши способности к телепортации с размещением блоков и музыкой, сделав музыкальное видео Minecraft. Не волнуйтесь, если вы не всё здесь понимаете, просто введите код в буфер и играйте, изменяя значения, пока код выполняется. Повеселитесь и увидимся в следующий раз…

    live_loop :note_blocks do
      mc_message "This is Sonic Minecraft"
      with_fx :reverb do
        with_fx :echo, phase: 0.125, reps: 32 do
          tick
          x = (range 30, 90, step: 0.1).look
          y = 20
          z = -10
          mc_teleport x, y, z
          ns = (scale :e3, :minor_pentatonic)
          n = ns.shuffle.choose
          bs = (knit :glass, 3, :sand, 1)
          b = bs.look
          synth :beep, note: n, release: 0.1
          mc_set_block b, x+20, n-60+y, z+10
          mc_set_block b, x+20, n-60+y, z-10
          sleep 0.25
        end
      end
    end
    live_loop :beats do
      sample :bd_haus, cutoff: 100
      sleep 0.5
    end

# - Ритмы Бизе

После нашего краткого экскурса в сказочный мир кодинга Minecraft в прошлом месяце, давайте снова помузицируем. Сегодня мы собираемся перенести классический оперный танцевальный ритм в 21-й век, используя грандиозную силу кода.

# - Возмутительно И Дерзко

Переместимся на машине времени в 1875 год. Композитор Бизе как раз закончил свою последнюю оперу “Кармен”. К сожалению, как и множество других прогрессивных, ломающих стереотипы музыкальных произведений, публика поначалу её не приняла, ведь она была слишком дерзкой и непохожей на другие оперы того времени. Печально, но Бизе умер за десять лет до того, как эта опера заработала ошеломляющий международный успех и стала одной из самых известных и часто исполняемых опер всех времён. Из сочувствия к этой трагедии, возьмем одну из главных тем оперы “Кармен”, и преобразуем её в современный формат музыки, который также слишком возмутителен и чужд большинству людей нашего времени - кодированную музыку!

# - Расшифровка Хабанеры

Пытаться кодировать всю оперу было бы сложноватой задачей для одной статьи, так что давайте сосредоточимся на одной из самых известных её частей - басовой партии Хабанеры:

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

# - Ноты

Ноты упорядочиваются слева направо, как слова в этой статьи, но имеют разную высоту. Высота относительно нотной партитуры обозначает высоту тона. Чем выше нота находится в партитуре, тем выше высоты тона.

Мы уже знаем, как изменить высоту ноты в Sonic Pi - либо используя цифры, такие как `play 75` и `play 80`, либо используя названия нот: `play :Е` и `play :F`. К счастью, каждой вертикальной позиции музыкальной партитуры соответствует определенная нота. Взгляните на эту удобную таблицу:

# - Паузы

Ноты представляют собой чрезвычайно богатый и выразительный вид кода, способного объединить сразу множество вещей. Поэтому дя вас не должно стать большим удивлением, что партитура может не только сказать вам, какие ноты играть, но также когда ноты играть не нужно . В программировании это эквивалентно `nil` или `null` - отсутствию значения. Другими словами, пауза - это отсутствие ноты.

Если вы внимательно посмотрите на партитуру, вы увидите, что это на самом деле сочетание горизонтальных линий с черными точками, которые представляют собой ноты, коротые нужно играть, и волнистых штук, которые представляют собой паузы. К счастью, Sonic Pi имеет очень удобное представление для пауз: `:r`, так, если мы выполним: `play :r`, он на самом деле сыграет тишину! Мы могли бы также написать `play :rest`, `play nil` или `play false` - это всё эквивалентные способы представления пауз.

# - Ритм

Наконец, нужно узнать ещё одну вещь - как расшифровывать в партитуре длительности нот. В оригинальной партитуре мы видим, что ноты связаны толстыми линиями, называемыми рёбрами. Вторая нота имеет два таких ребра, что означает, что она длится 16-ю часть такта. Другие ноты имеют одно ребро, которое означает, что они дляться 8-ю часть такта. Паузы имеют два волнистых флажка, которые означают, что они также длятся 16-ю часть такта.

Когда мы пытаемся расшифровать и изучить новые вещи, очень удобный приём - сделать всё как можно более однородным, чтобы увидеть соотношения и структуры. Например, если мы перепишем нашу партитуру одними только 16-ми длительностями, вы сможете увидеть, что она превращается в простую последовательность нот и пауз.

# - Повторное кодирование Хабанеры

Теперь мы в состоянии начать переводить эту басовую партию для Sonic Pi. Давайте закодируем эти ноты и паузы в кольцо:

    (ring :d, :r, :r, :a, :f5, :r, :a, :r)

Теперь посмотрим, как это звучит. Закиньте это кольцо в живой цикл, чтобы можно было последовательно извлекать элементы кольца:

    live_loop :habanera do
      play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
      sleep 0.25
    end

Легендарный, мгновенно узнаваемый рифф возвращается к жизни сквозь ваши колонки. Потребовалось немало усилий, чтобы добраться сюда, но это того стоило!

# - Мрачные Синты

Теперь у нас есть басовая партия. Давайте воссоздадим атмосферу оперной сцены. Попробуем осуществить это с `:blade`, мрачным солирующим синтом в стиле 80-х. Давайте испробуем его, извлекая ноту `:d`, пропущенную через эффекты нарезки и реверберации:

    live_loop :habanera do
      use_synth :fm
      use_transpose -12
      play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
      sleep 0.25
    end
    with_fx :reverb do
      live_loop :space_light do
        with_fx :slicer, phase: 0.25 do
          synth :blade, note: :d, release: 8, cutoff: 100, amp: 2
        end
        sleep 8
      end
    end

Теперь, попробуйте подставить туда другие ноты басовой партии:`:a` и `:f5`. Помните, вам не надо нажимать кнопку “Остановить”, просто измените код в то время, как музыка играет, и нажмите “Выполнить” снова. Также, попробуйте разные значения параметра `phase:` нарезки, такие как `0.5`, `0.75` и `1`.

# - Соединим Всё Вместе

Наконец, давайте объединим все идеи этой статьи в новый ремикс Хабанеры. Вы можете заметить, что я включил ещё одну часть басовой партии как комментарий. Как только вы набрали всё это в буфере, нажмите “Выполнить”, чтобы прослушать композицию. Затем, не нажимая кнопку “Остановить”, раскомментируйте вторую строку, удалив знак `#`, и нажмите “Выполнить” снова - как это удивительно! Итак, начинайте лайвкодинг и веселитесь!

    use_debug false
    bizet_bass = (ring :d, :r, :r, :a, :f5, :r, :a, :r)
    #bizet_bass = (ring :d, :r, :r, :Bb, :g5, :r, :Bb, :r)

    with_fx :reverb, room: 1, mix: 0.3 do
      live_loop :bizet do
        with_fx :slicer, phase: 0.125 do
          synth :blade, note: :d4, release: 8,
            cutoff: 100, amp: 1.5
        end
        16.times do
          tick
          play bizet_bass.look, release: 0.1
          play bizet_bass.look - 12, release: 0.3
          sleep 0.125
        end
      end
    end

    live_loop :ind do
      sample :loop_industrial, beat_stretch: 1,
        cutoff: 100, rate: 1
      sleep 1
    end

    live_loop :drums do
      sample :bd_haus, cutoff: 110
      synth :beep, note: 49, attack: 0,
        release: 0.1
      sleep 0.5
    end

# - Становимся Minecraft Виджеями

Все вы играли в Minecraft. Все строили удивительные сооружения, конструировали хитрые ловушки и даже создавали контролируемые транспортные линии. Но, держу пари, вы не догадывались, что могли бы использовать Minecraft для создания удивительных визуальных эффектов как профессиональный виджей.

Если вашим единственным способом игры с Minecraft была модификация игрового мира с помощью мышки, вам наверняка было бы трудно изменять его достаточно быстро. К счастью, ваш Raspberry Pi поставляется с версией Minecraft, управляемой с помощью кода. Он также содержит приложение Sonic Pi, которое делает кодирование Minecraft не только лёгким, но и невероятно весёлым.

В этой статье я покажу вам некоторые советы и трюки, использующиеся в выступлениях в ночных клубах и концертных площадках по всему миру.

Итак, начнём…

# - Приступая К Работе

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

    mc_message "Let's get started..."

Нажмите кнопку “Выполнить”, и вы увидите сообщение в окне Minecraft. Хорошо, мы готовы начать, давайте повеселимся……

# - Песчаные Бури

Когда мы используем Minecraft для создания визуальных эффектов, мы стараемся думать о том, чтобы это одновременно выглядело интересно и легко генерировалось с помощью кода. Интересный трюк - создать песчаную бурю, сбрасывая песчаные блоки с неба. Для этого нам необходимы несколько базовых функций:

`sleep` - для того, чтобы вставить задержку между действиями `mc_location` - для нахождения нашего текущего местоположения `mc_set_block`- чтобы поместить песчаный блок в заданное место `rrand` - для генерации случайных чисел в заданном диапазоне `live_loop` - позволяет сделать дождь из песка непрерывным

Если вы не знакомы с какой-либо из встроенных функций, например `rrand`, просто введите её название в свой буфер, кликните на нём, а затем используйте клавиатурное сочетание `Ctrl-i`, вызвающее встроенную документацию. В качестве альтернативы вы можете переместиться к вкладке язык справочной системы, и найти нужную функцию прямо там, как и другие интересные вещи.

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

    x, y, z = mc_location
    mc_set_block :sand, x, y + 20, z + 5
    sleep 2
    mc_set_block :sand, x, y + 20, z + 6
    sleep 2
    mc_set_block :sand, x, y + 20, z + 7
    sleep 2
    mc_set_block :sand, x, y + 20, z + 8

Когда вы нажмете “Выполнить”, вам, возможно, придется немного осмотреться, так как блоки могут начать падать позади вас в зависимости от того, в каком направлении вы в настоящее время смотрите. Не волнуйтесь, если вы пропустили их, просто нажмите “Выполнить” снова, и вы получите ещё одну порцию песчаного дождя - просто убедитесь, что вы смотрите в правильном направлении!

Давайте быстро посмотрим, что тут у нас происходит. На первой строке мы получили местоположение Стива в виде координат с помощью функции `mc_location` и присвоили их переменным `х`, `у`, и `z`. На последующих строках мы использовали функциию `mc_set_block`, чтобы поместить немного песка в тех же координатах, что и Стив но с некоторыми изменениями. Мы выбрали ту же координату `x`, но координата `y` стала на 20 блоков выше, а затем последовательно увеличивали `z`, чтобы песок падал в линию, удаляющуюся от Стива.

Почему бы вам самим не поиграть с этим кодом? Попробуйте добавить больше линий, изменените время задержки, попробуйте смешать `:sand` с `:gravel` и выбирать разные координаты. Просто экспериментируйте и веселитесь!

# - Раскручиваем Живые Циклы

Хорошо, пришло время получить бушующую бурю, высвободив мощь `live_loop` - магической способности Sonic Pi, раскрывающей всю силу лайвкодинга - изменения кода в реальном времени!

    live_loop :sand_storm do
      x, y, z = mc_location
      xd = rrand(-10, 10)
      zd = rrand(-10, 10)
      co = rrand(70, 130)
      synth :cnoise, attack: 0, release: 0.125, cutoff: co
      mc_set_block :sand, x + xd, y + 20, z + zd
      sleep 0.125
    end

Это весело! Мы выполняем круг цикла довольно быстро (8 раз в секунду), и во время каждого круга мы находим местоположение Стива также, как и раньше, но в этот раз генерируем 3 случайных значения:

`xd` - разница для `x`, которая будет находиться между -10 и 10 `zd` - разница для `z`, которая также будет между -10 и 10 `co` - значение среза фильтра низких частот между 70 и 130

Затем мы используем эти случайные значения в функциях `synth` и `mc_set_block`, что даёт нам песок, падающий случайным образом вокруг Стива вместе с перкуссионным звуком, похожим на дождь, от синтезатора `:cnoise`.

Для тех из вас, кто ещё новичок в живых циклах - именно здесь и начинается самое интересное. Пока код выполняется и песок сыплется вниз, попробуйте изменить одно из значений. Например, время задержки на `0.25`, или тип блока с `:sand` на `:gravel`. Теперь нажмите “Выполнить” снова. Эй! Всё изменилось без остановки кода. Это и есть та самая дверь к выступлениям в роли виджея. Продолжайте тренироваться и что-нибудь изменять. Насколько разнообразными можно сделать визуальные эффекты, не останавливая кода?

# - Эпические Блочные Структуры

Наконец, еще один отличный способ создания интересных визуальных эффектов - генерировать огромные повторяющиеся стены, парящие рядом. Для этого эффекта нам нужно перейти от размещения блоков случайным образом, к размещению их в упорядоченном виде. Мы можем сделать это с помощью двух вложеных итераций (нажмите кнопку “Помощь”, чтобы перейти в раздел 5.2 учебника “Итерации И Циклы”, чтобы узнать больше об итерациях). Аргумент `|xd|` после `do` означает, что `xd` будет соответствовать номеру итерации. Поэтому сначала это будет 0, потом 1, потом 2… и т. д. Совмещая две итерации вместе, мы можем сгенерировать любые координаты. Затем мы произвольно выбираем типы блоков из кольцевого списка для создания интересного эффекта:

    x, y, z = mc_location
    bs = (ring :gold, :diamond, :glass)
    10.times do |xd|
      10.times do |yd|
        mc_set_block bs.choose, x + xd, y + yd, z
      end
    end

Довольно аккуратно. В то время как мы здесь веселимся, попробуйте изменить `bs.choose`, на `bs.tick`, чтобы перейти от случайного выбора к последовательному. Попробуйте изменять типы блоков более радикально. Вы можете захотеть делать это с `live_loop`, чтобы узоры продолжали изменяться автоматически.

Теперь, измените обе итерации с `10.times` на `100.times` и нажмите “Выполнить”. Бабах! Огромные исполинские стены с хаотично расположенными кирпичами. Представьте сколько времени потребуется вам, чтобы построить их вручную с помощью мыши! Дважды нажмите пробел, чтобы переключиться в режим полёта и начните парить для создания замечательных визуальных эффектов. Не останавливайтесь на этом, используйте своё воображение, чтобы придумать интересные идеи, а затем, использовав силу кода Sonic Pi, сделайте это реальностью. Когда вы достаточно попрактикуетесь, приглушите свет и покажите шоу своим друзьям!

# - Surfing Random Streams

Back in episode 4 of this tutorial series we took a brief look at randomisation whilst coding up some sizzling synth riffs. Given that randomisation is such an important part of my live coding DJ sets I thought it would be useful to cover the fundamentals in much greater detail. So, get your lucky hat on and let’s surf some random streams!

# - There is no random

The first thing to learn which might really surprise you when playing with Sonic Pi’s randomisation functions is that they’re not actually really random. What does this actually mean? Well, let’s try a couple of tests. First, imagine a number in your head between 0 and 1. Keep it there and don’t tell me. Now let me guess… was it `0.321567`? No? Bah, I’m clearly no good at this. Let me have another go, but let’s ask Sonic Pi to choose a number this time. Fire up Sonic Pi v2.7+ and ask it for a random number but again don’t tell me:

    print rand

Now for the reveal… was it `0.75006103515625`? Yes! Ha, I can see you’re a little sceptical. Perhaps it was just a lucky guess. Let’s try again. Press the Run button again and see what we get… What? `0.75006103515625` again? This clearly can’t be random! You’re right, it’s not.

What’s going on here? The fancy computer science word here is determinism. This just means that nothing is by chance and everything is destined to be. Your version of Sonic Pi is destined to always return `0.75006103515625` in the program above. This might sound pretty useless, but let me assure you that it’s one of the most powerful parts of Sonic Pi. If you stick at it you’ll learn how to rely on the deterministic nature of Sonic Pi’s randomisation as a fundamental building block for your compositions and live coded DJ sets.

# - A Random Melody

When Sonic Pi boots it actually loads into memory a sequence of 441,000 pre-generated random values. When you call a random function such as `rand` or `rrand`, this random stream is used to generate your result. Each call to a random function consumes a value from this stream. Therefore the 10th call to a random function will use the 10th value from the stream. Also, every time you press the Run button, the stream is reset for that run. This is why I could predict the result to `rand` and why the ‘random’ melody was the same every time. Everybody’s version of Sonic Pi uses the exact same random stream which is very important when we start sharing our pieces with each other.

Let’s use this knowledge to generate a repeatable random melody:

    8.times do
     play rrand_i(50, 95)
     sleep 0.125
    end

Type this into a spare buffer and hit Run. You’ll hear a melody consisting of ‘random’ notes between 50 and 95. When it’s finished, hit Run again to hear exactly the same melody again.

## Handy Randomisation Functions

Sonic Pi comes with a number of useful functions for working with the random stream. Here’s a list of some of the most useful:

`rand` - Simply returns the next value in the random stream `rrand` - Returns a random value within a range `rrand_i` - Returns a random whole number within a range `one_in` - Returns true or false with the given probability `dice` - Imitates rolling a dice and returns a value between 1 and 6 `choose` - Chooses a random value from a list

Check out their documentation in the Help system for detailed information and examples.

# - Resetting the Stream

Whilst the ability to repeat a sequence of chosen notes is essential to allow you to replay a riff on the dance floor, it might not be exactly the riff you want. Wouldn’t it be great if we could try a number of different riffs and choose the one we liked best? This is where the real magic starts.

We can manually set the stream with the fn `use_random_seed`. In Computer Science, a random seed is the starting point from which a new stream of random values can sprout out and blossom. Let’s try it:

    use_random_seed 0
    3.times do
      play rrand_i(50, 95)
      sleep 0.125
    end

Great, we get the first three notes of our random melody above: `84`, `83` and `71`. However, we can now change the seed to something else. How about this:

    use_random_seed 1
    3.times do
      play rrand_i(50, 95)
      sleep 0.125
    end

Interesting, we get `83`, `71` and `61` . You might notice that the first two numbers here are the same as the last two numbers before - this isn’t a coincidence.

Remember that the random stream is just a giant list of ‘pre-rolled’ values. Using a random seed simply jumps us to a point in that list. Another way of thinking about it is to imagine a huge deck of pre-shuffled cards. Using a random seed is cutting the deck at a particular point. The fabulous part of this is that it’s precisely this ability to jump around the random stream which gives us huge power when making music.

Let’s revisit our random melody of 8 notes with this new stream resetting power, but let’s also throw in a live loop so we can experiment live whilst it’s playing:

    live_loop :random_riff do
      use_random_seed 0
      8.times do
        play rrand_i(50, 95), release: 0.1
        sleep 0.125
      end
    end

Now, whilst it’s still playing, change the seed value from `0` to something else. Try `100`, what about `999`. Try your own values, experiment and play around - see which seed generates the riff you like best.

# - Соединим Всё Вместе

This month’s tutorial has been quite a technical dive into the workings of Sonic Pi’s randomisation functionality. Hopefully it has given you some insight into how it works and how you can start using randomisation in a reliable way to create repeatable patterns within your music. It’s important to stress that you can use repeatable randomisation anywhere you want. For example, you can randomise the amplitude of notes, the timing of the rhythm, the amount of reverb, the current synth, the mix of an FX, etc. etc. In the future we’ll take a close look at some of these applications, but for now let me leave you with a short example.

Type the following into a spare buffer, hit Run, and then start changing the seeds around, hit Run again (whilst it’s still playing) and explore the different sounds, rhythms and melodies you can make. When you find a nice one, remember the seed number so you can get back to it. Finally, when you’ve found a few seeds you like, put on a live coded performance for your friends by simply switching between your favourite seeds to create a full piece.

    live_loop :random_riff do
      use_random_seed 10300
      use_synth :prophet
      s = [0.125, 0.25, 0.5].choose
      8.times do
        r = [0.125, 0.25, 1, 2].choose
        n = (scale :e3, :minor).choose
        co = rrand(30, 100)
        play n, release: r, cutoff: co
        sleep s
      end
    end
    live_loop :drums do
      use_random_seed 2001
      16.times do
        r = rrand(0.5, 10)
        sample :drum_bass_hard, rate: r, amp: rand
        sleep 0.125
      end
    end

# - Controlling Your Sound

So far during this series we’ve focussed on triggering sounds. We’ve discovered that we can trigger the many synths built into Sonic Pi with `play` or `synth` and how to trigger pre-recorded samples with `sample`. We’ve also looked at how we can wrap these triggered sounds within studio FX such as reverb and distortion using the `with_fx` command. Combine this with Sonic Pi’s incredibly accurate timing system and you can produce a vast array of sounds, beats and riffs. However, once you’ve carefully selected a particular sound’s options and triggered it, there’s no ability to mess with it whilst it’s playing right? Wrong! Today you’re going to learn something very powerful - how to control running synths.

## A Basic Sound

Let’s create a nice simple sound. Fire up Sonic Pi and in a fresh buffer type the following:

    synth :prophet, note: :e1, release: 8, cutoff: 100

Now press the Run button at the top left to hear a lovely rumbling synth sound. Go ahead, press it again a few times to get a feel for it. OK, done? Let’s start controlling it!

## Synth Nodes

A little known feature in Sonic Pi is that the fns `play`, `synth` and `sample`, return something called a `SynthNode` which represents a running sound. You can capture one of these `SynthNode`s using a standard variable and then control it at a later point in time. For example, let’s change the value of the `cutoff:` opt after 1 beat:

    sn = synth :prophet, note: :e1, release: 8, cutoff: 100
    sleep 1
    control sn, cutoff: 130

Let’s look at each line in turn:

Firstly we trigger the `:prophet` synth using the `synth` fn as normal. However we also capture the result in a variable called `sn`. We could have called this variable something completely different such as `synth_node` or `jane` - the name doesn’t matter. However, it’s important to choose a name that’s meaningful to you for your performances and for people reading your code. I chose `sn` as it’s a nice short mnemonic for synth node.

On line 2 we have a standard `sleep` command. This does nothing special - it just asks the computer to wait for 1 beat before moving onto the next line.

Line 3 is where the control fun starts. Here, we use the `control` fn to tell our running `SynthNode` to change the cutoff value to `130`. If you hit the Run button, you’ll hear the `:prophet` synth start playing as before, but after 1 beat it will shift to sound a lot brighter.

Modulatable Options

Most of Sonic Pi’s synths and FX opts may be changed after being triggered. However, this isn’t the case for all of them. For example, the envelope opts `attack:`, `decay:`, `sustain:` and `release:` can only be set when triggering the synth. Figuring out which opts can and can’t be changed is simple - just head to the documentation for a given synth or FX and then scroll down to the individual option documentation and look for the phrases “May be changed whilst playing” or “Can not be changed once set”. For example, the documentation for the `:beep` synth’s `attack:` opt makes it clear that it’s not possible to change it:

Default: 0 Must be zero or greater Can not be changed once set Scaled with current BPM value

## Multiple Changes

Whilst a synth is running you’re not limited to changing it only once - you’re free to change it as many times as you like. For example, we can turn our `:prophet` into a mini arpeggiator with the following:

    notes = (scale :e3, :minor_pentatonic)
    sn = synth :prophet, note: :e1, release: 8, cutoff: 100
    sleep 1
    16.times do
      control sn, note: notes.tick
      sleep 0.125
    end

In this snippet of code we just added a couple of extra things. First we defined a new variable called `notes` which contains the notes we’d like to cycle through (an arpeggiator is just a fancy name for something that cycles through a list of notes in order). Secondly we replaced our single call to `control` with an iteration calling it 16 times. In each call to `control` we `.tick` through our ring of `notes` which will automatically repeat once we get to the end (thanks to the fabulous power of Sonic Pi’s rings). For a bit of variety try replacing `.tick` with `.choose` and see if you can hear the difference.

Note that we can change multiple opts simultaneously. Try changing the control line to the following and listen for the difference:

    control sn, note: notes.tick, cutoff: rrand(70, 130)

## Sliding

When we control a `SynthNode`, it responds exactly on time and instantly changes the value of the opt to the new one as if you’d pressed a button or flicked a switch requesting the change. This can sound rhythmical and percussive - especially if the opt controls an aspect of the timbre such as `cutoff:`. However, sometimes you don’t want the change to happen instantaneously. Instead, you might want to smoothly move from the current value to the new one as if you’d moved a slider or dial. Of course, Sonic Pi can also do this too using the `_slide:` opts.

Each opt that can be modified also has a special corresponding `_slide:` opt that allows you to specify a slide time. For example, `amp:` has `amp_slide:` and `cutoff:` has `cutoff_slide:`. These slide opts work slightly differently than all the other opts in that they tell the synth note how to behave next time they are controlled. Let’s take a look:

    sn = synth :prophet, note: :e1, release: 8, cutoff: 70, cutoff_slide: 2
    sleep 1
    control sn, cutoff: 130

Notice how this example is exactly the same as before except with the addition of `cutoff_slide:`. This is saying that next time this synth has its `cutoff:` opt controlled, it will take 2 beats to slide from the current value to the new one. Therefore, when we use `control` you can hear the cutoff slide from 70 to 130. It creates an interesting dynamic feel to the sound. Now, try changing the `cutoff_slide:` time to a shorter value such as 0.5 or a longer value such as 4 to see how it changes the sound. Remember, you can slide any of the modifiable opts in exactly this way and each `_slide:` value can be totally different so you can have the cutoff sliding slowly, the amp sliding fast and the pan sliding somewhere in between if that’s what you’re looking to create…

## Соединим Всё Вместе

Let’s look at a short example which demonstrates the power of controlling synths after they’ve been triggered. Notice that you can also slide FX just like synths although with a slightly different syntax. Check out section 7.2 of the built-in tutorial for more information on controlling FX.

Copy the code into a spare buffer and take a listen. Don’t stop there though - play around with the code. Change the slide times, change the notes, the synth, the FX and the sleep times and see if you can turn it into something completely different!

    live_loop :moon_rise do
      with_fx :echo, mix: 0, mix_slide: 8 do |fx|
        control fx, mix: 1
        notes = (scale :e3, :minor_pentatonic, num_octaves: 2).shuffle
        sn = synth :prophet , sustain: 8, note: :e1, cutoff: 70, cutoff_slide: 8
        control sn, cutoff: 130
        sleep 2
        32.times do
          control sn, note: notes.tick, pan: rrand(-1, 1)
          sleep 0.125
        end
      end
    end

# - Tracking the Beat

Last month in this series we took a deep technical dive into the randomisation system underpinning Sonic Pi. We explored how we can use it to deterministically add new levels of dynamic control over our code. This month we’re going to continue our technical dive and turn our attention to Sonic Pi’s unique tick system. By the end of this article you’ll be ticking your way through rhythms and riffs on your way to being a live coding DJ.

# - Beat Counting

When making music we often want to do a different thing depending on which beat it is. Sonic Pi has a special beat counting system called `tick` to give you precise control over when a beat actually occurs and even supports multiple beats with their own tempos.

Let’s have a play - to advance the beat we just need to call `tick`. Open up a fresh buffer, type in the following and hit Run:

    puts tick #=> 0

This will return the current beat: `0`. Notice that even if you press the Run button a few times it will always return `0`. This is because each run starts a fresh beat counting from 0. However, whilst the run is still active, we can advance the beat as many times as we want:

    puts tick #=> 0
    puts tick #=> 1
    puts tick #=> 2

Whenever you see the symbol `#=>` at the end of a line of code it means that that line will log the text on the right-hand-side. For example, `puts foo #=> 0` means the code `puts foo` prints `0` to the log at that point in the program.

# - Checking the Beat

We’ve seen that `tick` does two things. It increments (adds one) and returns the current beat. Sometimes we just want to look at the current beat without having to increment it which we can do via `look`:

    puts tick #=> 0
    puts tick #=> 1
    puts look #=> 1
    puts look #=> 1

In this code we tick the beat up twice and then call `look` twice. We’ll see the following values in the log: `0`, `1`, `1`, `1`. The first two `tick`s returned `0`, then `1` as expected, then the two `look`s just returned the last beat value twice which was `1`.

# - Кольца

So now we can advance the beat with `tick` and check the beat with `look`. What next? We need something to tick over. Sonic Pi uses rings for representing riffs, melodies and rhythms and the tick system has been specifically designed to work very closely with them. In fact, rings have their own dot version of `tick` which does two things. Firstly, it acts like a regular tick and increments the beat. Secondly it looks up the ring value using the beat as the index. Let’s take a look:

    puts (ring :a, :b, :c).tick #=> :a

`.tick` is a special dot version of `tick` which will return the first value of the ring `:a`. We can grab each of the values in the ring by calling `.tick` multiple times:

    puts (ring :a, :b, :c).tick #=> :a
    puts (ring :a, :b, :c).tick #=> :b
    puts (ring :a, :b, :c).tick #=> :c
    puts (ring :a, :b, :c).tick #=> :a
    puts look                   #=> 3

Take a look at the log and you’ll see `:a`, `:b`, `:c` and then `:a` again. Notice that `look` returns `3`. Calls to `.tick` act just like they are regular calls to `tick` - they increment the local beat.

# - A Live Loop Arpeggiator

The real power comes when you mix `tick` with rings and `live_loop`s. When combined we have all the tools we need to both build and understand a simple arpegiator. We need just four things:

A ring containing the notes we want to loop over. A means of incrementing and obtaining the beat. The ability to play a note based on the current beat. A loop structure to keep the arpegiator repeating.

These concepts can all be found in the following code:

    notes = (ring 57, 62, 55, 59, 64)
    live_loop :arp do
      use_synth :dpulse
      play notes.tick, release: 0.2
      sleep 0.125
    end

Let’s look at each of these lines. First we define our ring of notes which we’ll continually play. We then create a `live_loop` called `:arp` which loops round for us. Each time round the `live_loop` we set our synth to `:dpulse` and then play the next note in our ring using `.tick`. Remember that this will increment our beat counter and use the latest beat value as an index into our notes ring. Finally, we wait for an eighth of a beat before looping round again.

# - Multiple Simultaneous Beats

A really important thing to know is that `tick`s are local to the `live_loop`. This means that each `live_loop` has its own independent beat counter. This is much more powerful than having a global metronome and beat. Let’s take a look at this in action:

    notes = (ring 57, 62, 55, 59, 64)
    with_fx :reverb do
      live_loop :arp do
        use_synth :dpulse
        play notes.tick + 12, release: 0.1
        sleep 0.125
      end
    end
    live_loop :arp2 do
      use_synth :dsaw
      play notes.tick - 12, release: 0.2
      sleep 0.75
    end

# - Clashing Beats

A big cause of confusion with Sonic Pi’s tick system is when people want to tick over multiple rings in the same `live_loop`:

    use_bpm 300
    use_synth :blade
    live_loop :foo do
      play (ring :e1, :e2, :e3).tick
      play (scale :e3, :minor_pentatonic).tick
      sleep 1
    end

Even though each `live_loop` has its own independent beat counter, we’re calling `.tick` twice within the same `live_loop`. This means that the beat will be incremented twice every time round. This can produce some interesting polyrhythms but is often not what you want. There are two solutions to this problem. One option is to manually call `tick` at the start of the `live_loop` and then use `.look` to look up the current beat in each `live_loop`. The second solution is to pass a unique name to each call to `.tick` such as `.tick(:foo)`. Sonic Pi will then create and track a separate beat counter for each named tick you use. That way you can work with as many beats as you need! See the section on named ticks in 9.4 of the built-in tutorial for more information.

# - Соединим Всё Вместе

Let’s bring all this knowledge of `tick`s, `ring`s and `live_loop`s together for a final fun example. As usual, don’t treat this as a finished piece. Start changing things and play around with it and see what you can turn it into. See you next time…

    use_bpm 240
    notes = (scale :e3, :minor_pentatonic).shuffle
    live_loop :foo do
      use_synth :blade
      with_fx :reverb, reps: 8, room: 1 do
        tick
        co = (line 70, 130, steps: 32).tick(:cutoff)
        play (octs :e3, 3).look, cutoff: co, amp: 2
        play notes.look, amp: 4
        sleep 1
      end
    end
    live_loop :bar do
      tick
      sample :bd_ada if (spread 1, 4).look
      use_synth :tb303
      co = (line 70, 130, steps: 16).look
      r = (line 0.1, 0.5, steps: 64).mirror.look
      play notes.look, release: r, cutoff: co
      sleep 0.5
    end

# - Sample Slicing

Way back in episode 3 of this Sonic Pi series we looked at how to loop, stretch and filter one of the most famous drum breaks of all time - the Amen Break. In this tutorial we’re going to take this one step further and learn how to slice it up, shuffle the slices and glue it back together in a completely new order. If that sounds a bit crazy to you, don’t worry, it will all become clear and you’ll soon master a powerful new tool for your live coded sets.

# - Sound as Data

Before we get started let’s just take a brief moment to understand how to work with samples. By now, you’ve all hopefully played with Sonic Pi’s powerful sampler. If not, there’s no time like the present! Boot up your Raspberry Pi, launch Sonic Pi from the Programming menu, type the following into a fresh buffer and then hit the Run button to hear a pre-recorded drum beat:

    sample :loop_amen

A recording of a sound is simply represented as data - lots of numbers between -1 and 1 which represent the peaks and troughs of the sound wave. If we play those numbers back in order, we get the original sound. However, what’s to stop us from playing them back in a different order and creating a new sound?

How are samples actually recorded? It’s actually pretty simple once you understand the basic physics of sound. When you make a sound - for example by hitting a drum, the noise travels through the air in a similar fashion to how the surface of a lake ripples when you throw a pebble into it. When those ripples reach your ears, your eardrum moves sympathetically and converts those movements into the sound you hear. If we wish to record and play back the sound, we therefore need a way of capturing, storing and reproducing those ripples. One way is to use a microphone which acts like an eardrum and moves back and forth as the sound ripples hit it. The microphone then converts its position into a tiny electric signal which is then measured many times a second. These measurements are then represented as a series of numbers between -1 and 1.

If we were to plot a visualisation of the sound it would be a simple graph of data with time on the x axis and microphone/speaker position as a value between -1 and 1 on the y axis. You can see an example of such a graph at the top of the diagram.

# - Playing Part of a Sample

So, how do we code Sonic Pi to play a sample back in a different order? To answer this question we need to take a look at the `start:` and `finish:` opts for `sample`. These let us control the start and finish positions of our playback of the numbers which represent the sound. The values for both of these opts are represented as a number between `0` and `1` where `0` represents the start of the sample and `1` is the end. So, to play the first half of the Amen Break, we just need to specify a `finish:` of `0.5`:

    sample :loop_amen, finish: 0.5

We can add in a `start:` value to play an even smaller section of the sample:

    sample :loop_amen, start: 0.25, finish: 0.5

For fun, you can even have the `finish:` opt’s value be before `start:` and it will play the section backwards:

    sample :loop_amen, start: 0.5, finish: 0.25

# - Re-ordering Sample Playback

Now that we know that a sample is simply a list of numbers that can be played back in any order and also how to play a specific part of a sample we can now start having fun playing a sample back in the ‘wrong’ order.

Let’s take our Amen Break and chop it up into 8 equally-sized slices and then shuffle the pieces around. Take a look at the diagram: at the top A) represents the graph of our original sample data. Chopping it into 8 slices gives us B) - notice that we’ve given each slice a different colour to help distinguish them. You can see each slice’s start and finish values at the top. Finally C) is one possible re-ordering of the slices. We can then play this back to create a new beat. Take a look at the code to do this:

    live_loop :beat_slicer do
      slice_idx = rand_i(8)
      slice_size = 0.125
      s = slice_idx * slice_size
      f = s + slice_size
      sample :loop_amen, start: s, finish: f
      sleep sample_duration :loop_amen, start: s, finish: f
    end

we choose a random slice to play which should be a random number between 0 and 7 (remember that we start counting at 0). Sonic Pi has a handy function for exactly this: `rand_i(8)`. We then store this random slice index in the variable `slice_idx`. We define our `slice_size` which is 1/8 or 0.125. The `slice_size` is necessary for us to convert our `slice_idx` into a value between 0 and 1 so we can use it as our `start:` opt. We calculate the start position `s` by multiplying the `slice_idx` by the `slice_size`. We calculate the finish position `f` by adding the `slice_size` to the start position `s`. We can now play the sample slice by plugging in the `s` and `f` values into the `start:` and `finish:` opts for `sample`. Before we play the next slice we need to know how long to `sleep` which should be the duration of the sample slice. Luckily, Sonic Pi has us covered with `sample_duration` which accepts all the same opts as `sample` and simply returns the duration. Therefore, by passing `sample_duration` our `start:` and `finish:` opts, we can find out the duration of a single slice. We wrap all of this code in a `live_loop` so that we continue to pick new random slices to play.

## Соединим Всё Вместе

Let’s combine everything we’ve seen so far into a final example which demonstrates how we can take a similar approach to combine randomly sliced beats with some bass to create the start of an interesting track. Now it’s your turn - take the code below as a starting point and see if you can take it in your own direction and create something new…

    live_loop :sliced_amen do
      n = 8
      s =  line(0, 1, steps: n).choose
      f = s + (1.0 / n)
      sample :loop_amen, beat_stretch: 2, start: s, finish: f
      sleep 2.0  / n
    end
    live_loop :acid_bass do
      with_fx :reverb, room: 1, reps: 32, amp: 0.6 do
        tick
        n = (octs :e0, 3).look - (knit 0, 3 * 8, -4, 3 * 8).look
        co = rrand(70, 110)
        synth :beep, note: n + 36, release: 0.1, wave: 0, cutoff: co
        synth :tb303, note: n, release: 0.2, wave: 0, cutoff: co
        sleep (ring 0.125, 0.25).look
      end
    end

# - Code a Probabilistic Sequencer

In a previous episode of this Sonic Pi series we explored the power of randomisation to introduce variety, surprise and change into our live coded tracks and performances. For example, we randomly picked notes from a scale to create never-ending melodies. Today we’re going to learn a new technique which uses randomisation for rhythm - probabilistic beats!

# - Переносимость

Before we can start making new beats and synth rhythms we need to take a quick dive into the basics of probability. This might sound daunting and complicated, but really it’s just as simple as rolling a dice - honestly! When you take a regular 6 sided board game dice and roll it what’s actually happening? Well, firstly you’ll roll either a 1, 2, 3, 4, 5 or 6 with exactly the same chance of getting any of the numbers. In fact, given that it’s a 6 sided dice, on average (if you roll lots and lots of times) you’ll throw a 1 every 6 throws. This means you have a 1 in 6 chance of throwing a 1. We can emulate dice rolls in Sonic Pi with the fn `dice`. Let’s roll one 8 times:

    8.times do
      puts dice
      sleep 1
    end

Notice how the log prints values between 1 and 6 just as if we’d rolled a real dice ourselves.

# - Начальные Точки Случайных Чисел

Послушаем, на что это похоже:

    live_loop :random_beat do
      sample :drum_snare_hard if dice == 1
      sleep 0.125
    end

Let’s quickly go over each line to make sure everything is very clear. First we create a new `live_loop` called `:random_beat` which will continually repeat the two lines between `do` and `end`. The first of these lines is a call to `sample` which will play a pre-recorded sound (the `:drum_snare_hard` sound in this case). However, this line has a special conditional `if` ending. This means that the line will only be executed if the statement on the right hand side of the `if` is `true`. The statement in this case is `dice == 1`. This calls our `dice` function which, as we have seen, returns a value between 1 and 6. We then use the equality operator `==` to check to see if this value is `1`. If it is `1`, then the statement resolves to `true` and our snare drum sounds, if it isn’t `1` then the statement resolves to `false` and the snare is skipped. The second line simply waits for `0.125` seconds before rolling the dice again.

# - Changing Probabilities

Those of you that have played role play games will be familiar with lots of strangely shaped dice with different ranges. For example there is the tetrahedron shaped dice which has 4 sides and even a 20 sided dice in the shape of a icosahedron. The number of sides on the dice changes the chance, or probability of rolling a 1. The fewer sides, the more likely you are to roll a 1 and the more sides the less likely. For example, with a 4 sided dice, there’s a one in 4 chance of rolling a 1 and with a 20 sided dice there’s a one in 20 chance. Luckily, Sonic Pi has the handy `one_in` fn for describing exactly this. Let’s play:

    live_loop :different_probabilities do
      sample :drum_snare_hard if one_in(6)
      sleep 0.125
    end

Start the live loop above and you’ll hear the familiar random rhythm. However, don’t stop the code running. Instead, change the `6` to a different value such as `2` or `20` and hit the `Run` button again. Notice that lower numbers mean the snare drum sounds more frequently and higher numbers mean the snare triggers fewer times. You’re making music with probabilities!

# - Combining Probabilities

Things get really exciting when you combine multiple samples being triggered with different probabilities. For example:

    live_loop :multi_beat do
      sample :elec_hi_snare if one_in(6)
      sample :drum_cymbal_closed if one_in(2)
      sample :drum_cymbal_pedal if one_in(3)
      sample :bd_haus if one_in(4)
      sleep 0.125
    end

Again, run the code above and then start changing the probabilities to modify the rhythm. Also, try changing the samples to create an entirely new feel. For example try changing `:drum_cymbal_closed` to `:bass_hit_c` for extra bass!

# - Ритм

Next, we can use our old friend `use_random_seed` to reset the random stream after 8 iterations to create a regular beat. Type the following code to hear a much more regular and repeating rhythm. Once you hear the beat, try changing the seed value from `1000` to another number. Notice how different numbers generate different beats.

    live_loop :multi_beat do
      use_random_seed 1000
      8.times do
        sample :elec_hi_snare if one_in(6)
        sample :drum_cymbal_closed if one_in(2)
        sample :drum_cymbal_pedal if one_in(3)
        sample :bd_haus if one_in(4)
        sleep 0.125
      end
    end

One thing I tend to do with this kind of structure is to remember which seeds sound good and make a note of them. That way I can easily re-create my rhythms in future practice sessions or performances.

# - Соединим Всё Вместе

Finally, we can throw in some random bass to give it some nice melodic content. Notice that we can also use our newly discovered probabilistic sequencing method on synths just as well as samples. Don’t leave it at that though - tweak the numbers and make your own track with the power of probabilities!

    live_loop :multi_beat do
      use_random_seed 2000
      8.times do
        c = rrand(70, 130)
        n = (scale :e1, :minor_pentatonic).take(3).choose
        synth :tb303, note: n, release: 0.1, cutoff: c if rand < 0.9
        sample :elec_hi_snare if one_in(6)
        sample :drum_cymbal_closed if one_in(2)
        sample :drum_cymbal_pedal if one_in(3)
        sample :bd_haus, amp: 1.5 if one_in(4)
        sleep 0.125
      end
    end

# - Амплитуда

This month we’re going to take a deep dive into one of Sonic Pi’s most powerful and flexible audio FX - the `:slicer`. By the end of this article you will have learned how to manipulate the overall volume of parts of our live coded sound in powerful new ways. This will allow you to create new rhythmic and timbral structures and broaden your sonic possibilities.

## Slice that Amp

So, what does the `:slicer` FX actually do? One way to think about it is that it’s just like having someone play around with the volume control on your TV or home hi-fi. Let’s take a look but first, listen to the deep growl of the following code which triggers the `:prophet` synth:

    synth :prophet, note: :e1, release: 8, cutoff: 70
    synth :prophet, note: :e1 + 4, release: 8, cutoff: 80

Now, let’s pipe it through the `:slicer` FX:

    with_fx :slicer do
      synth :prophet, note: :e1, release: 8, cutoff: 70
      synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
    end

Hear how the slicer acts like it’s muting and unmuting the audio with a regular beat. Also, notice how the `:slicer` affects all the audio generated between the `do`/`end` blocks. You can control the speed at which it turns the audio on and off with the `phase:` opt which is short for phase duration. Its default value is `0.25` which means 4 times a second at the default BPM of 60. Let’s make it faster:

    with_fx :slicer, phase: 0.125 do
      synth :prophet, note: :e1, release: 8, cutoff: 70
      synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
    end

Now, play with different `phase:` durations yourself. Try longer and shorter values. See what happens when you choose a really short value. Also, try different synths such as `:beep` or `:dsaw` and different notes. Take a look at the following diagram to see how different `phase:` values change the number of amplitude changes per beat.

Phase duration is the length of time for one on/off cycle. Therefore smaller values will make the FX switch on and off much faster than larger values. Good values to start playing with are `0.125`, `0.25`, `0.5` and `1`.

## Контроль волн

By default, the `:slicer` FX uses a square wave to manipulate the amplitude through time. This is why we hear the amplitude on for a period, then immediately off for a period, then back on again. It turns out that the square wave is just one of 4 different control waves that are supported by `:slicer`. The others are saw, triangle and (co)sine. Take a look at the diagram below to see what these look like. We can also hear what they sound like. For example, the following code uses (co)sine as the control wave. Hear how the sound doesn’t turn on and off abruptly but instead smoothly fades in and out:

    with_fx :slicer, phase: 0.5, wave: 3 do
      synth :dsaw, note: :e3, release: 8, cutoff: 120
      synth :dsaw, note: :e2, release: 8, cutoff: 100
    end

Have a play with the different wave forms by changing the `wave:` opt to `0` for saw, `1` for square, `2` for triangle and `3` for sine. See how different waves sound with different `phase:` opts too.

Each of these waves can be inverted with the `invert_wave:` opt which flips it on the y axis. For example, in a single phase the saw wave typically starts high, and slowly goes down before jumping back to the top. With `invert_wave: 1` it will start low and slowly go up before jumping back down again. Additionally, the control wave can be started at different points with the `phase_offset:` opt which should be a value between `0` and `1`. By playing around with `phase:`, `wave:`, `invert_wave:` and `phase_offset` opts you can dramatically change how the amplitude is modified through time.

## Устанавливаем собственные уровни

By default, `:slicer` switches between amplitude values `1` (fully loud) and `0` (silent). This can be changed with the `amp_min:` and `amp_max:` opts. You can use this alongside the sine wave setting to create a simple tremolo effect:

    with_fx :slicer, amp_min: 0.25, amp_max: 0.75, wave: 3, phase: 0.25 do
      synth :saw, release: 8
    end

This is just like grabbing the volume knob on your hi-fi and moving it up and down just a little so the sound ‘wobbles’ in and out.

## Вероятности

One of `:slicer`’s powerful features is its ability to use probability to choose whether or not to turn the slicer on or off. Before the `:slicer` FX starts a new phase it rolls a dice and based on the result either uses the selected control wave or keeps the amplitude off. Let’s take a listen:

    with_fx :slicer, phase: 0.125, probability: 0.6  do
      synth :tb303, note: :e1, cutoff_attack: 8, release: 8
      synth :tb303, note: :e2, cutoff_attack: 4, release: 8
      synth :tb303, note: :e3, cutoff_attack: 2, release: 8
    end

Hear how we now have an interesting rhythm of pulses. Try changing the `probability:` opt to a different value between `0` and `1`. Values closer to `0` will have more space between each sound due to the likelihood of the sound being triggered being much lower.

Another thing to notice is that the probability system in the FX is just like the randomisation system accessible via fns such as `rand` and `shuffle`. They are both completely deterministic. This means that each time you hit Run you’ll hear exactly the same rhythm of pulses for a given probability. If you would like to change things around you can use the `seed:` opt to select a different starting seed. This works exactly the same as `use_random_seed` but only affects that particular FX.

Finally, you can change the ‘resting’ position of the control wave when the probability test fails from `0` to any other position with the `prob_pos:` opt:

    with_fx :slicer, phase: 0.125, probability: 0.6, prob_pos: 1  do
      synth :tb303, note: :e1, cutoff_attack: 8, release: 8
      synth :tb303, note: :e2, cutoff_attack: 4, release: 8
      synth :tb303, note: :e3, cutoff_attack: 2, release: 8
    end

## “Нарезаем” биты

One really fun thing to do is to use `:slicer` to chop a drum beat in and out:

    with_fx :slicer, phase: 0.125 do
      sample :loop_mika
    end

This allows us to take any sample and create new rhythmical possibilites which is a lot of fun. However, one thing to be careful about is to make sure that the tempo of the sample matches the current BPM in Sonic Pi otherwise the slicing will sound totally off. For example, try swapping `:loop_mika` with the `loop_amen` sample to hear how bad this can sound when the tempos don’t align.

## Изменяем темп

As we have already seen, changing the default BPM with `use_bpm` will make all the sleep times and synth envelope durations grow or shrink to match the beat. The `:slicer` FX honours this too, as the `phase:` opt is actually measured in beats not seconds. We can therefore fix the issue with `loop_amen` above by changing the BPM to match the sample:

    use_sample_bpm :loop_amen
    with_fx :slicer, phase: 0.125 do
      sample :loop_amen
    end

## Соединим Всё Вместе

Let’s apply all these ideas into a final example that only uses the `:slicer` FX to create an interesting combination. Go ahead, start changing it and make it into your own piece!

    live_loop :dark_mist do
      co = (line 70, 130, steps: 8).tick
      with_fx :slicer, probability: 0.7, prob_pos: 1 do
        synth :prophet, note: :e1, release: 8, cutoff: co
      end

      with_fx :slicer, phase: [0.125, 0.25].choose do
        sample :guit_em9, rate: 0.5
      end
      sleep 8
    end
    live_loop :crashing_waves do
      with_fx :slicer, wave: 0, phase: 0.25 do
        sample :loop_mika, rate: 0.5
      end
      sleep 16
    end

# - Пять техник лайв-кодинга

In this month’s Sonic Pi tutorial we’re going to take a look at how you can start treating Sonic Pi like a real instrument. We therefore need to start thinking of code in a completely different way. Live coders think of code in a similar way to how violinists think of their bow. In fact, just like a violinist can apply various bowing techniques to create different sounds (long slow motions vs short fast hits) we will explore five of the basic live coding techniques that Sonic Pi enables. By the end of this article you’ll be able to start practicing for your own live coded performances.

## 1. Memorise the Shortcuts

The first tip to live coding with Sonic Pi is to start using the shortcuts. For example, instead of wasting valuable time reaching for the mouse, moving it over to the Run button and clicking, you can simply press `alt` and `r` at the same time which is much faster and keeps your fingers at the keyboard ready for the next edit. You can find out the shortcuts for the main buttons at the top by hovering the mouse over them. See section 10.2 of the built-in tutorial for the full list of shortcuts.

When performing, one fun thing to do is to add a bit of flair with your arm motion when hitting shortcuts. For example, it’s often good to communicate to the audience when you’re about to make a change - so embellish your movement when hitting `alt-r` just like a guitarist would do when hitting a big power chord.

## 2. Manually Layer your Sounds

Now you can trigger code instantly with the keyboard, you can instantly apply this skill for our second technique which is to layer your sounds manually. Instead of ‘composing’ using lots of calls to `play`, and `sample` separated by calls to `sleep` we will have one call to `play` which we will manually trigger using `alt-r`. Let’s try it. Type the following code into a fresh buffer:

    synth :prophet, note: :e1, release: 8, cutoff: 100

Now, hit `Run` and whilst the sound is playing, modify the code in order to drop down four notes by changing it to the following:

    synth :prophet, note: :e1, release: 8, cutoff: 100

Now, hit `Run` again, to hear both sounds playing at the same time. This is because Sonic Pi’s `Run` button doesn’t wait for any previous code to finish, but instead starts the code running at the same time. This means you can easily layer lots of sounds manually with minor or major modifications between each trigger. For example, try changing both the `note:` and the `cutoff:` opts and then re-trigger.

Также вы можете опробовать эту технику с длинными абстрактными сэмплами:

    sample :ambi_lunar_land

Try starting the sample off, and then progressively halving the `rate:` opt between hitting `Run` from `1` to `0.5` to `0.25` to `0.125` and then even try some negative values such as `-0.5`. Layer the sounds together and see where you can take it. Finally, try adding some FX.

When performing, working with simple lines of code in this way means that an audience new to Sonic Pi has a good chance to follow what you’re doing and relate the code that they can read to the sounds they are hearing.

## Живые циклы

When working with more rhythmic music, it can often be hard to manually trigger everything and keep good time. Instead, it is often better to use a `live_loop`. This provides repetition for your code whilst also giving the ability to edit the code for the next time round the loop. They also will run at the same time as other `live_loop`s which means you can layer them together both with each other and manual code triggers. Take a look at section 9.2 of the built-in tutorial for more information about working with live loops.

When performing, remember to make use of `live_loop`’s `sync:` opt to allow you to recover from accidental runtime mistakes which stop the live loop running due to an error. If you already have the `sync:` opt pointing to another valid `live_loop`, then you can quickly fix the error and re-run the code to re-start things without missing a beat.

## 4. Use the Master Mixer

One of Sonic Pi’s best kept secrets is that it has a master mixer through which all sound flows. This mixer has both a low pass filter and a high pass filter built-in, so you can easily perform global modifications to the sound. The master mixer’s functionality can be accessed via the fn `set_mixer_control!`. For example, whilst some code is running and making sound, enter this into a spare buffer and hit `Run`:

`set_mixer_control! lpf: 50`

After you run this code, all existing and new sounds will have a low pass filter applied to them and will therefore sound more muffled. Note that this means that the new mixer values stick until they are changed again. However, if you want, you can always reset the mixer back to its default state with `reset_mixer!`. Some of the currently supported opts are: `pre_amp:`, `lpf:` `hpf:`, and `amp:`. For the full list, see the built-in docs for `set_mixer_control!`.

Use the mixer’s `*_slide` opts to slide one or many opts values over time. For example, to slowly slide the mixer’s low pass filter down from the current value to 30, use the following:

    set_mixer_control! lpf_slide: 16, lpf: 30

Затем вы можете быстро перескочить обратно к высокому значению:

    set_mixer_control! lpf_slide: 1, lpf: 130

When performing, it’s often useful to keep a buffer free for working with the mixer like this.

## 5. Практика

The most important technique for live coding is practice. The most common attribute across professional musicians of all kinds is that they practice playing with their instruments - often for many hours a day. Practice is just as important for a live coder as a guitarist. Practice allows your fingers to memorise certain patterns and common edits so you can type and work with them more fluently. Practice also gives you opportunities to explore new sounds and code constructs.

When performing, you’ll find the more practice you do, the easier it will be for you to relax into the gig. Practice will also give you a wealth of experience to draw from. This can help you understand which kinds of modifications will be interesting and also work well with the current sounds.

## Соединим Всё Вместе

This month, instead of giving you a final example that combines all the things discussed, let’s part by setting down a challenge. See if you can spend a week practicing one of these ideas every day. For example, one day practice manual triggers, the next do some basic `live_loop` work and the following day play around with the master mixer. Then repeat. Don’t worry if things feel slow and clunky at first - just keep practicing and before you know it you’ll be live coding for a real audience.

# - 8 Советов, которые помогут вам при лайв-кодинге

Last month we took a look at five important techniques for mastering live coding - in other words, we explored how we could use Sonic Pi to approach code in the same way we would approach a musical instrument. One of the important concepts that we discussed was practice. This month we’re going to take a deeper dive into understanding why live coding practice is important and how you might start.

## Регулярно практикуйтесь

The most important piece of advice is to make sure you practice regularly. As a rule I typically practice for 1-2 hours a day, but 20 mins is just fine when you’re starting out. Little but often is what you’re aiming for - so if you can only manage 10 minutes, that’s a great start.

Practice tip #1 - start to develop a practice routine. Find a nice time in the day that works for you and try and practice at that time as many days of the week as you can. Before long you’ll be looking forward to your regular session.

## Научитесь слепому набору

If you watch a professional musician performing on stage you’ll likely notice a few things. Firstly, when they play they don’t stare at their instrument. Their fingers, arms and bodies know which keys to press, strings to pluck or drums to hit without them having to think about it too much. This is known as “muscle memory” and although it might sound like something only professionals can do - it’s just the same as when you first learned to walk or ride a bike - practicing through repetition. Live coders use muscle memory to free their minds from having to think about where to move their fingers so they can focus on the music. This is called touch-typing - typing without having to look at the keyboard.

Практический совет #2 - тренируйтесь слепой печати. Есть множество приложений, вебсайтов и даже игр, которые могут помочь вам в этом деле. Найдите то, которое вам нравится и поупражняйтесь в нём, пока у вас не получится набирать текст не глядя.

## Программируйте стоя

The body of a musician is conditioned for playing their instrument. For example, a trumpet player needs to be able to blow hard, a guitar player needs to be able to grip the fretboard with strength and a drummer needs to be able to continually hit the drums for long periods of time. So, what’s physical about live coding? Just like DJs, live coders typically perform whilst standing up and some even dance whilst they code! If you practice live coding whilst sitting at a desk and then have to get up and stand at a gig, you’ll likely find the difference very difficult and frustrating.

Practice tip #3 - stand whilst you practice. The easiest way to do this is to use a standing height desk. However, if like me you don’t have one at home, there’s a couple of low-fi options. The approach I take is to use an ironing board which happens to work rather well. Another is to stack some boxes or large books on a normal desk and place your keyboard on top of that. Also, make sure you stretch before you start practicing and try and dance a little during the session. Remember, nobody is watching you, so have fun and you’ll feel much more natural on stage.

## Практикуйтесь в развёртке оборудования

Most instruments require some assembly and tuning before they can be played. Unless you’re a rockstar with a bus full of roadies, you’ll have to set up your own instrument before your gig. This is often a stressful time and it is easy for problems to occur. One way to help with this is to incorporate the setup process into your practice sessions.

Practice tip #4 - treat setting up as an important part of your practice. For example, have a box or bag that you can keep your Raspberry Pi and keyboard in etc. Before each practice session, take out all the parts, connect everything, and work through the boot process until you have Sonic Pi running and can make sounds. Once you’ve finished practicing, take the time to carefully pack everything away afterwards. This may take some time at first, but before long you’ll be able to setup and pack everything away incredibly quickly without having to think about it.

## Проводите множество музыкальных экспериментов

Once you’ve set up and are ready to start making music, you might find yourself struggling to know where to start. One problem many people face is that they might have a good idea of the kinds of sounds they want to make, but are frustrated that they can’t produce them. Some people don’t even know what kind of sounds they want to make! The first thing to do is not to worry - this is very common and happens to every musician - even if they’ve been practicing for a long time. It is much more important to be making sounds you don’t like than not making any sounds at all.

Practice tip #5 - spend time making sounds and music you don’t like. Try to make time to explore new sounds and ideas. Don’t worry that it might sound terrible if it’s not the style you’re looking for. When you’re experimenting like this you increase the chance of stumbling over a sound or combination of sounds which you love! Even if 99% of the sounds you make are bad, that 1% might be the riff or intro to your new track. Forget the things you don’t like and remember the parts you do. This is even easier when you’re making music with code - just hit save!

## Учитесь слышать код

Many musicians can look at a musical score and hear the music in their head without having to play it. This is a very useful skill and it’s well worth incorporating into your live coding practice sessions. The imporant point is to be able to have some understanding of what the code is going to sound like. You don’t need to be able to hear it exactly in your head, but instead it’s useful to know if the code is going to be fast, slow, loud, rhythmic, melodic, random, etc. The final goal is then to be able to reverse this process - to be able to hear music in your head and know what code to write to make it. It may take you a long time to master this, but once you do, you’ll be able to improvise on stage and express your ideas fluently.

Practice tip #6 - write some code into Sonic Pi but don’t hit the Run button. Instead, try to imagine what sound it is going to produce. Then, hit Run, listen, and think about what you got right and what you didn’t. Keep repeating this until it become a natural part of your coding process. When I practice I normally have a good idea of what the code will sound like. However, I still am occasionally surprised, and then I’ll stop and spend some time thinking about why I was wrong. Each time this happens, I learn new tricks which allow me to express myself in new ways.

## Устраните все отвлекающие факторы

A common problem when practicing is to become distracted with other things. Practicing is hard and requires real discipline regardless of the kind of music you’re making - from jazz to classical to EDM. If you’re struggling to get started or make progress, it’s often too easy to hop on social media, or look something up on the internet etc. If you’ve set yourself a target of 20 minutes of practice, it’s important to try and spend all that time being as productive as possible.

Practice tip #7 - before you start practicing remove as many distractions as possible. For example, disconnect from the internet, put your phone in another room and try to practice in a quiet place where you’re unlikely to be disturbed. Try to focus on coding music and you can return to your distractions when you’ve finished.

## Ведите дневник практики

When you are practicing, you’ll often find your mind is full of new exciting ideas - new musical directions, new sounds to try out, new functions to write, etc. These ideas are often so interesting that you might stop what you’re doing and start working on the idea. This is another form of distraction!

Practice tip #8 - keep a practice diary by your keyboard. When you get an exciting new idea, temporarily pause your practice session, quickly jot the idea down, then forget about it and carry on practicing. You can then spend some quality time thinking about and working on your ideas after you’ve finished practicing.

## Соединим Всё Вместе

Try to establish a practice routine which incorporates as many of these ideas as possible. Try to keep the sessions as fun as possible but be aware that some practice sessions will be hard and feel a little like work. However, it will all be worth it once you’ve created your first piece or given your first performance. Remember, practice is the key to success!

# - Растяжение Ритмов

When people discover Sonic Pi, one of the first things they learn is how simple it is to play pre-recorded sounds using the `sample` function. For example, you can play an industrial drum loop, hear the sound of a choir or even listen to a vinyl scratch all via a single line of code. However, many people don’t realise that you can actually vary the speed that the sample is played back at for some powerful effects and a whole new level of control over your recorded sounds. So, fire up a copy of Sonic Pi and let’s get started stretching some samples!

# - Сэмплы

To modify the playback rate of a sample we need to use the `rate:` opt:

    sample :guit_em9, rate: 0.5

If we specify a `rate:` of `1` then the sample is played back at the normal rate. If we want to play it back at half speed we simply use a `rate:` of `0.5`:

    sample :guit_em9, rate: 0.5

choose

# - Сэмплы

In addition to making the sound longer and lower using a small rate, we can use higher rates to make the sound shorter and higher. Let’s play with a drum loop this time. First, take a listen to how it sounds at the default rate of `1`:

    sample :loop_amen, rate: -1

Now, let’s speed it up a little:

    sample :loop_amen, rate: 1.5

Ha! We just moved musical genres from old-skool techno to jungle. Notice how the pitch of each drum hit is higher as well as how the whole rhythm speeds up. Now, try even higher rates and see how high and short you can make the drum loop. For example, if you use a rate of `100`, the drum loop turns into a click!

# - Reverse Gear

Now, I’m sure many of you are thinking the same thing right now… “what if you use a negative number for the rate?”. Great question! Let’s think about this for a moment. If our `rate:` opt signifies the speed with which the sample is played back, `1` being normal speed, `2` being double speed, `0.5` being half speed, `-1` must mean backwards! Let’s try it on a snare. First, play it back at the normal rate:

    sample :elec_filt_snare, rate: 1

Круто! Он играет задом-наперед!

    sample :elec_filt_snare, rate: -1

Of course, you can play it backwards twice as fast with a rate of `-2` or backwards at half speed with a rate of `-0.5`. Now, play around with different negative rates and have fun. It’s particularly amusing with the `:misc_burp` sample!

## Sample, Rate and Pitch [Sidebar]

One of the effects of rate modification on samples is that faster rates result in the sample sounding higher in pitch and slower rates result in the sample sounding lower in pitch. Another place you may have heard this effect in every day life is when you’re cycling or driving past a beeping pedestrian crossing - as you’re heading towards the sound source the pitch is higher than when you’re moving away from the sound - the so-called Doppler effect. Why is this?

Let’s consider a simple beep which is represented by a sine wave. If we use an oscilloscope to plot a beep, we’ll see something like Figure A. If we plot a beep an octave higher, we’ll see Figure B and an octave lower will look like Figure C. Notice that the waves of higher notes are more compact and the waves of lower notes are more spread out.

A sample of a beep is nothing more than a lot of numbers (x, y, coordinates) which when plotted onto a graph will re-draw the original curves. See figure D where each circle represents a coordinate. To turn the coordinates back into audio, the computer works through each x value and sends the corresponding y value to the speakers. The trick here is that the rate at which the computer works through the x numbers does not have to be the same as the rate with which they were recorded. In other words, the space (representing an amount of time) between each circle can be stretched or compressed. So, if the computer walks through the x values faster than the original rate, it will have the effect of squashing the circles closer together which will result in a higher sounding beep. It will also make the beep shorter as we will work through all the circles faster. This is shown in Figure E.

Finally, one last thing to know is that a mathematician called Fourier proved that any sound is actually lots and lots of sine waves all combined together. Therefore, when we compress and stretch any recorded sound we’re actually stretching and compressing many sine waves all at the same time in exactly this manner.

# - Pitch Bending

As we’ve seen, using a faster rate will make the sound higher in pitch and a slower rate will make the sound lower in pitch. A very simple and useful trick is to know that doubling the rate actually results in the pitch being an octave higher and inversely halving the rate results in the pitch being an octave lower. This means that for melodic samples, playing it alongside itself at double/half rates actually sounds rather nice:

    sample :bass_trance_c, rate: 1
    sample :bass_trance_c, rate: 2
    sample :bass_trance_c, rate: 0.5

However, what if we just want to alter the rate such that the pitch goes up one semitone (one note up on a piano)? Sonic Pi makes this very easy via the `rpitch:` opt:

    sample :bass_trance_c
    sample :bass_trance_c, rpitch: 3
    sample :bass_trance_c, rpitch: 7

If you take a look at the log on the right, you’ll notice that an `rpitch:` of `3` actually corresponds to a rate of `1.1892` and a `rpitch:` of `7` corresponds to a rate of `1.4983`. Finally, we can even combine `rate:` and `rpitch:` opts:

    sample :ambi_choir, rate: 0.25, rpitch: 3
    sleep 3
    sample :ambi_choir, rate: 0.25, rpitch: 5
    sleep 2
    sample :ambi_choir, rate: 0.25, rpitch: 6
    sleep 1
    sample :ambi_choir, rate: 0.25, rpitch: 1

# - Соединим Всё Вместе

Let’s take a look at a simple piece which combines these ideas. Copy it into an empty Sonic Pi buffer, hit play, listen to it for a while and then use it as a starting point for your own piece. See how much fun it is to manipulate the playback rate of samples. As an added exercise try recording your own sounds and play around with the rate to see what crazy sounds you can make.

    live_loop :beats do
      sample :guit_em9, rate: [0.25, 0.5, -1].choose, amp: 2
      sample :loop_garzul, rate: [0.5, 1].choose
      sleep 8
    end

    live_loop :melody do
      oct = [-1, 1, 2].choose * 12
      with_fx :reverb, amp: 2 do
        16.times do
          n = (scale 0, :minor_pentatonic).choose
          sample :bass_voxy_hit_c, rpitch: n + 4 + oct
          sleep 0.125
        end
      end
    end

# - Additive Synthesis

This is the first of a short series of articles on how to use Sonic Pi for sound design. We’ll be take a quick tour of a number of different techniques available for you to craft your own unique sound. The first technique we’ll look at is called additive synthesis. This may sound complicated - but if we expand each word slightly the meaning pops right out. Firstly, additive means a combination of things and secondly synthesis means to create sound. Additive synthesis therefore means nothing more complicated than combining existing sounds to create new ones. This synthesis technique dates back a very long time - for example, pipe organs in the middle ages had lots of slightly different sounding pipes which you could enable or disable with stops. Pulling out the stop for a given pipe ‘added it to the mix’ making the sound richer and more complex. Now, let’s see how we can pull out all the stops with Sonic Pi.

# - Simple Combinations

Let’s start with the most basic sound there is - the humble pure-toned sine wave:

    synth :sine, note: :d3

Now, let’s see how this sounds combined with a square wave:

    synth :sine, note: :d3
    synth :square, note: :d3

Notice how the two sounds combine to form a new, richer sound. Of course, we don’t have to stop there, we can add as many sounds as we need. However, we need to be careful with how many sounds we add together. Just like when we mix paints to create new colours, adding too many colours will result in a messy brown, similarly - adding too many sounds together will result in a muddy sound.

# - Blending

Let’s add something to make it sound a little brighter. We could use a triangle wave at an octave higher (for that high bright sound) yet only play it at amp `0.4` so it adds something extra to the sound rather than taking it over:

    synth :sine, note: :d3
    synth :square, note: :d3
    synth :tri, note: :d4, amp: 0.4

Now, try creating your own sounds by combining 2 or more synths at different octaves and amplitudes. Also, note that you can play around with each synth’s opts to modify each source sound before it is mixed in for even more combinations of sounds.

# - Detuning

So far, when combining our different synths we’ve used either the same pitch or switched octave. How might it sound if we didn’t stick to octaves but instead chose a slightly higher or lower note? Let’s try it:

    detune = 0.7
    synth :square, note: :e3
    synth :square, note: :e3 + detune

If we detune our square waves by 0.7 notes we hear something that perhaps doesn’t sound in tune or correct - a ‘bad’ note. However, as we move closer to 0 it will sound less and less out of tune as the pitches of the two waves get closer and more similar. Try it for yourself! Change the `detune:` opt value from `0.7` to `0.5` and listen to the new sound. Try `0.2`, `0.1`, `0.05`, `0`. Each time you change the value, take a listen and see if you can hear how the sound is changing. Notice that low detune values such as `0.1` produce a really nice ‘thick’ sound, with both slightly different pitches interacting with each other in interesting, often surprising, ways.

`:dsaw`

# - Амплитуда

Another way we can finely craft our sound is to use a different envelope and options for each synth trigger. For example this will allow you to make some aspects of the sound percussive and other aspects ring out for a period of time.

    detune = 0.1
    synth :square, note: :e1, release: 2
    synth :square, note: :e1 + detune, amp: 2, release: 2
    synth :gnoise, release: 2, amp: 1, cutoff: 60
    synth :gnoise, release: 0.5, amp: 1, cutoff: 100
    synth :noise, release: 0.2, amp: 1, cutoff: 90

In the example above I have mixed in a noisy percussive element to the sound along with some more persistent background rumbling. This was achieved firstly by using two noise synths with middling cutoff values (`90` and `100`) using short release times along with a noise with a longer release time but with a low cutoff value (which makes the noise less crisp and more rumbly.)

# - Соединим Всё Вместе

Let’s combine all these techniques to see if we can use additive synthesis to re-create a basic bell sound. I’ve broken this example into four sections. Firstly we have the ‘hit’ section which is the initial onset part of the bell sound - so uses a short envelope (e.g. a `release:` of around `0.1`). Next we have the long ringing section in which I’m using the pure sound of the sine wave. Notice that I’m often increasing the note by roughly `12` and `24` which are the number of notes in one and two octaves. I have also thrown in a couple of low sine waves to give the sound some bass and depth. Finally, I used `define` to wrap my code in a function which I can then use to play a melody. Try playing your own melody and also messing around with the contents of the `:bell` function until you create your own crazy sound to play with!

    define :bell do |n|
      # Triangle waves for the 'hit'
      synth :tri, note: n - 12, release: 0.1
      synth :tri, note: n + 0.1, release: 0.1
      synth :tri, note: n - 0.1, release: 0.1
      synth :tri, note: n, release: 0.2
      # Sine waves for the 'ringing'
      synth :sine, note: n + 24, release: 2
      synth :sine, note: n + 24.1, release: 2
      synth :sine, note: n + 24.2, release: 0.5
      synth :sine, note: n + 11.8, release: 2
      synth :sine, note: n, release: 2
      # Low sine waves for the bass
      synth :sine, note: n - 11.8, release: 2
      synth :sine, note: n - 12, release: 2
    end
    # Play a melody with our new bell!
    bell :e3
    sleep 1
    bell :c2
    sleep 1
    bell :d3
    sleep 1
    bell :g2

# - Subtractive Synthesis

This is the second in a series of articles on how to use Sonic Pi for sound design. Last month we looked at additive synthesis which we discovered was the simple act of playing multiple sounds at the same time to make a new combined sound. For example we could combine different sounding synths or even the same synth at different pitches to build a new complex sound from simple ingredients. This month we’ll look at a new technique commonly called subtractive synthesis which is simply the act of taking an existing complex sound and removing parts of it to create something new. This is a technique which is commonly associated with the sound of analog synthesisers of the 1960s and 1970s but also with the recent renaissance of modular analog synths through popular standards such as Eurorack.

Despite this sounding like a particularly complicated and advanced technique, Sonic Pi makes it surprisingly simple and easy - so let’s dive right in.

# - Complex Source Signal

For a sound to work well with subtractive synthesis, it typically needs to be fairly rich and interesting. This doesn’t mean we need something hugely complex - in fact, just a standard `:square` or `:saw` wave will do:

    synth :saw, note: :e2, release: 4

Notice that this sound is already pretty interesting and contains many different frequencies above `:e2` (the second E on a piano) which add to create the timbre. If that didn’t make much sense to you, try comparing it with the `:beep`:

    synth :beep, note: :e2, release: 4

As the `:beep` synth is just a sine wave, you’ll hear a much purer tone and only at `:e2` and none of the high crispy/buzzy sounds which you heard in the `:saw`. It’s this buzziness and variation from a pure sine wave that we can play with when we use subtractive synthesis.

# - Фильтры

Once we have our raw source signal, the next step is to pass it through a filter of some kind which will modify the sound by removing or reducing parts of it. One of the most common filters used for subtractive synthesis is something called a low pass filter. This will allow all the low parts of the sound through but will reduce or remove the higher parts. Sonic Pi has a powerful yet simple to use FX system that includes a low pass filter, called `:lpf`. Let’s play with it:

    with_fx :lpf, cutoff: 100 do
      synth :saw, note: :e2, release: 4
    end

If you listen carefully you’ll hear how some of that buzziness and crispiness has been removed. In fact, all the frequencies in the sound above note `100` have been reduced or removed and only the ones below are still present in the sound. Try changing that `cutoff:` point to lower notes, say `70` and then `50` and compare the sounds.

Of course, the `:lpf` isn’t the only filter you can use to manipulate the source signal. Another important FX is the high pass filter referred to as `:hpf` in Sonic Pi. This does the opposite to `:lpf` in that it lets the high parts of the sound through and cuts off the low parts.

    with_fx :hpf, cutoff: 90 do
      synth :saw, note: :e2, release: 4
    end

Notice how this sounds much more buzzy and raspy now that all the low frequency sounds have been removed. Play around with the cutoff value - notice how lower values let more of the original bass parts of the source signal through and higher values sound increasingly tinny and quiet.

# - [Low Pass Filter] - breakout box

`:prophet`

# - Filter Modulation

So far we’ve just produced fairly static sounds. In other words, the sound doesn’t change in any way for the entirety of its duration. Often you might want some movement in the sound to give the timbre some life. One way to achieve this is via filter modulation - changing the filter’s options through time. Luckily Sonic Pi gives you powerful tools to manipulate an FX’s opts through time. For example, you can set a slide time to each modulatable opt to specify how long it should take for the current value to linearly slide to the target value:

    with_fx :lpf, cutoff: 50 do |fx|
      control fx, cutoff_slide: 3, cutoff: 130
      synth :prophet, note: :e2, sustain: 3.5
    end

Let’s take a quick look at what’s going on here. Firstly we start an `:lpf` FX block as normal with an initial `cutoff:` of a very low `20`. However, the first line also finishes with the strange `|fx|` at the end. This is an optional part of the `with_fx` syntax which allows you to directly name and control the running FX synth. Line 2 does exactly this and controls the FX to set the `cutoff_slide:` opt to 4 and the new target `cutoff:` to be `130`. The FX will now start sliding the `cutoff:` opt’s value from `50` to `130` over a period of 3 beats. Finally we also trigger a source signal synth so we can hear the effect of the modulated low pass filter.

# - Соединим Всё Вместе

This is just a very basic taster of what’s possible when you use filters to modify and change a source sound. Try playing with Sonic Pi’s many built-in FX to see what crazy sounds you can design. If your sound feels too static, remember you can start modulating the options to create some movement.

Let’s finish by designing a function which will play a new sound created with subtractive synthesis. See if you can figure out what’s going on here - and for the advanced Sonic Pi readers out there - see if you can work out why I wrapped everything inside a call to `at` (please send answers to @samaaron on Twitter).

    define :subt_synth do |note, sus|
      at do
        with_fx :lpf, cutoff: 40, amp: 2 do |fx|
          control fx, cutoff_slide: 6, cutoff: 100
          synth :prophet, note: note, sustain: sus
        end
        with_fx :hpf, cutoff_slide: 0.01 do |fx|
          synth :dsaw, note: note + 12, sustain: sus
          (sus * 8).times do
            control fx, cutoff: rrand(70, 110)
            sleep 0.125
          end
        end
      end
    end
    subt_synth :e1, 8
    sleep 8
    subt_synth :e1 - 4, 8

# - Необходимые Знания

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

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

# - Использование Клавиатурных Сочетаний

Sonic Pi такой же инструмент, как и среда разработки. Следовательно, клавиатурные сочетания моуг сделать работу c Sonic Pi намного более эффективной и естественной - особенно когда вы играете вживую перед аудиторией.

Многое в Sonic Pi может контролироваться с помощью клавиатуры. Когда вы лучше познакомитесь с работой и выступлениями с Sonic Pi, вы, вероятно, начнёте использовать клавиатурные сочетания всё чаще и чаще. Лично я печатаю вслепую (рекомендую обдумать возможность обучения этому навыку) и огорчаюсь всякий раз, когда мне нужно тянуться за мышкой, так как это меня замедляет. Поэтому я использую все эти клавиатурные сочетания на постоянной основе!

Следовательно, если вы изучите эти клавиатурные сочетания, вы узнаете, как эффективно использовать клавиатуру, и вы начнёте кодировать вживую как профи в кратчайшие сроки.

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

## Согласованность Всех Платформ

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

К сожалению три основные операционные системы (Linux, Mac ОС X и Windows) поставляются с собственными стандартами по умолчанию для таких действий, как вырезать, вставить и т. д. Sonic Pi будет пытаться соблюдать эти стандарты. Однако, вместо попыток соответствовать стандартам текущей платформы, Sonic Pi приоритетное внимание уделяет согласованности между платформами. Это значит, что если вы изучите сочетания клавиш во время игры с Sonic Pi на Raspberry Pi, то сможете перейти на Mac или PC и чувствовать себя там как дома.

## Control и Meta

Частью понятия согласованности является именование клавиатурных сочетаний. В Sonic Pi мы используем имена Control и Meta, ссылаясь на две главные комбинации клавиш. На всех платформах Control один и тот же (Ctrl). Однако, на Linux и Windows, Meta - это клавиша Alt, в то время как на Mac, Meta - это клавиша Command. Для единообразия мы будем использовать термин Meta - только не забудьте сопоставить его с соответствующей клавишей вашей операционной системы.

## Аббревиатуры

Чтобы сохранить вещи простыми и читабельными, мы будем использовать аббревиатуры - С- для Control плюс ещё одна клавиша, и М- - для Meta плюс ещё одна клавиша. Например, если клавиатурное сочетание требует от нас нажать одновременно Meta и r, мы напишем это как `M-r`. Символ - означает “одновременно с”.

Ниже приведены клавиатурные сочетания, которые я считаю самыми полезными.

## Выполнение и Остановка

Вместо того, чтобы постоянно тянуться за мышью, чтобы выполнить свой код, вы можешьте просто нажать `M-r`. Аналогично, чтобы остановить выполнение кода, вы можешьте нажать `M-s`.

## Навигация

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

Вы можете двигаться к началу строки, используя `C-a`, к концу строки, используя `C-e`, на строку вверх - `C-p`, на строку вниз - `C-n`, на символ вперёд - `C-f`, и на символ назад - `C-b`.

## Аккуратный Код

Чтобы применить автовыравнивание к вашему коду, просто нажмите `M-m`

## Справочная Система

Для переключения к справочной системе вы можете нажать `M-i`. Однако, гораздо полезнее знать сочетание `C-i`, которое будет искать слово под курсором в документации и отображать её, если что-нибудь найдет. Мгновенная помощь!

Чтобы увидеть полный список клавиатурных сочетаний, загляните в раздел 10.2 Шпаргалка по клавиатурным сочетаниям.

# - Шпаргалка По Клавиатурным Сочетаниям

Ниже приводится обзор основных клавиатурных сочетаний, доступных в Sonic Pi. Пожалуйста, посмотрите раздел 10.1 для подготовки и мотивации.

## Соглашения

В этом списке мы используем следующие соглашения (где Meta называется Alt в Windows/Linux или Cmd в Mac):

`C-a` значит удерживая клавишу Control, нажмите клавишу a. И после того, как обе клваиши будут нажаты одновременно, отпустите их. `M-r` значит удерживая клавишу Meta, нажмите клавишу r. И после того, как обе клваиши будут нажаты одновременно, отпустите их. `S-M-z` значит удерживая клавиши Shift и Meta, нажмите клавишу z. И после того, как все три клваиши будут нажаты одновременно, отпустите их. `C-M-f` значит удерживая клавиши Control и Meta, нажмите клавишу f. И после того, как все три клваиши будут нажаты одновременно, отпустите их.

## Основные Манипуляции С Приложением

`M-r` - Выполнить код `M-s` - Остановить выполнение кода `M-i` - Показать/скрыть справочную систему `M-p` - Показать/скрыть настройки `M-{` - Переключить буфер влево `M-}` - Переключить буфер вправо `M-+` - Увеличить размер текста в текущем буфере `M--` - Уменьшить размер текста в текущем буфере

## Выделение/Копирование/Вставка

`M-a` - Выбрать всё `M-c` - Копировать выделение в буфер обмена `M-]` - Копировать выделение в буфер обмена `M-x` - Вырезать выделение в буфер обмена `C-]` - Вырезать выделение в буфер обмена `C-k` - Вырезать от курсора до конца строки `M-v` - Вставить из буфера обмена в редактор `C-y` - Вставить из буфера обмена в редактор `C-SPACE` - Установить метку. Теперь навигация управляет областью выделения. Используйте `C-g` для отмены.

## Работа С Тексом

`M-m` - Выровнять весь текст `Tab` - Выровнять текущую линию/выделение `C-l` - Отобразить буфер с текущей строкой по центру экрана `M-/` - Комментировать/раскомментировать текущую строку `C-t` - Перемещение/замена символов `M-u` - Преобразовать следующее слово (или выделение) в верхний регистр `M-l` - Преобразовать следующее слово (или выделение) в нижний регистр

## Навигация

`C-a` - Перейти в начало строки `C-e` - Перейти в конец строки `C-p` - Перейти на предыдущую строку `C-n` - Перейти на следующую строку `C-f` - Перейти вперёд на один символ `C-b` - Перейти назад на один символ `M-f` - Перейти вперёд на одно слово `M-b` - Перейти назад на одно слово `C-M-n` - Переместить строку или выделение вниз `C-M-p` - Переместить строку или выделение вверх `S-M-u` - Подняться на 10 строк `S-M-d` - Опуститься на 10 строк `M-<` - Перейти в начало буфера `M->` - Перейти в конец буфера

## Удаление

`C-h` - Удалить предыдущий символ `C-d` - Удалить следующий символ

## Расширенные Возможности Редактора

`C-i` - Показать документацию по слову под курсором `M-z` - Отмена `S-M-z` - Повтор `C-g` - Escape `S-M-f` - Переключение полноэкранного режима `S-M-b` - Показать/скрыть кнопоки `S-M-l` - Показать/скрыть журнал `S-M-m` - Переключение между светлым и тёмным режимом `S-M-s` - Сохранить содержание буфера в файл `S-M-o` - Загрузить содержания из файла в буфер

# - Обмен

Sonic Pi создан для обучения и обмена друг с другом.

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

Если вы не уверены, какой способ поделиться своей работой с остальными лучший, я рекомендую размещать свой код на GitHub и музыку на SoundCloud. Таким образом вы сможете охватить большую аудиторию.

## Код -> GitHub

GitHub - это сайт для обмена и работы с кодом. Он используется профессиональными разработчиками, а также художниками для обмена и совместной работы с кодом. Самый простой способ поделиться новым куском кода (или даже незавершённым куском) - создать Gist. Gist - это простой способ загружать свой код в удобной форме, чтобы другие могли увидеть, скопировать и поделиться им.

## Аудио -> SoundCloud

Еще один отличный способ поделиться вашей работой - сделать аудио запись и загрузить её на SoundCloud. После того как вы загрузили свою запись, другие пользователи могут комментировать и обсуждать её. Я также рекомендую поместить ссылку на ваш код в Gist в описание трека.

Для того, чтобы записать свою работу, нажмите кнопку `Запись` в панели инструментов, и запись начнётся немедленно. Нажмите кнопку `Выполнить`, чтобы запустить свой код, если он ещё не запущен. Когда вы закончите запись, нажмите мигающую кнопку `Запись` снова, и вам будет предложено ввести имя файла. Запись будет сохранена в формате WAV-файл, который можно редактировать и конвертировать любым аудиоредактором с открытым исходным кодом (попробуйте, например, Audacity).

## Надежда

Я призываю вас делиться своей работой и на самом деле надеюсь, что мы все будем учить друг друга новым трюкам и развиваться вместе с Sonic Pi. Я действительно очень воодушевлён тем, что у вас будет, что показать мне.

# - Выступление

Один из самых интересных аспектов Sonic Pi заключается в том, что он позволяет использовать код как музыкальный инструмент. Это значит, что написание кода вживую может теперь рассматриваться как новый вид музыкального исполнения.

Мы называем это Лайвкодинг.

## Показывай Свой Экран

Я рекомендую вам показывать сой экран аудитории во время лайвкодинга. Это как играть на гитаре, но скрывая свои пальцы и струны. Когда я практикуюсь дома, я использую Raspberry Pi и небольшой мини-проектор, направленный на стену моей гостинной. Вы можете использовать свой телевизор или один из своих школьных/рабочих проекторов для своего шоу. Попробуйте, это очень весело.

## Собери группу

Don’t just play on your own - form a live coding band! It’s a lot of fun jamming with others. One person could do beats, another ambient background, etc. Use the `live_audio` functionality to combine code with traditional instruments such as a guitar or a microphone.

See what interesting combinations of sounds you can create with code.

## TOPLAP

Кодирование вживую не такая уж и новинка - небольшое количество людей делало это в течение последних нескольких лет, обычно используя самописные системы, которые они сконструировали для себя сами. Отличное место для того, чтобы узнать больше о других людях, занимающихся лайвкодингом и их системах, это TOPLAP.

## Алгорэйв

Ещё один отличный ресурс для изучения лайвкодинга, это Algorave. Здесь вы можете найти всё о конкретном направлении лайвкодинга - создании музыки в ночных клубах.

# - Minecraft Pi

Sonic Pi теперь поддерживает простой API для взаимодействия с Minecraft Pi - специальным изданием Minecraft, которое устанавливается по умолчанию в Raspbian - операционную систему на основе Linux.

## Нет Нужды Импортировать Библиотеки

Интеграция в Minecraft Pi была разработана с целью быть безумно простой в использовании. Все, что вам нужно сделать, это запустить Minecraft Pi и создать мир. Затем можно свободно использовать `mc_*` функции так, как если бы вы могли использовать `play` и `synth`. Не надо ничего импортировать или устанавливать какие-либо библиотеки - все готово и работает из коробки.

## Автоматическое Подключение

Minecraft Pi API отвечает за управление подключением в приложении Sonic Pi. Это означает, что вам не надо беспокоиться ни о чем. Если вы попытаетесь использовать Minecraft API, пока Minecraft не запущен, Sonic Pi вежливо сообщит вам об этом. Аналогично, если закрыть Minecraft Pi в то время, как всё ещё повторяется цикл `live_loop`, использующий Minecraft API, цикл остановится и Sonic Pi вежливо скажет вам, что не может подключиться к Minecraft. Чтобы переподключиться, просто запустите Minecraft снова и Sonic Pi автоматически обнаружит и заново создаст подключение.

## Разработано Для Лайвкодинга

Minecraft Pi API был разработан для безупречной работы с циклами `live_loop`. Это значит, что можно синхронизировать изменения в вашем Minecraft Pi мире с изменениями звука в Sonic Pi. Мгновенные, основанные на Minecraft, музыкальные клипы! Заметим, однако, что Minecraft Pi - альфа версия программы и, как известно, немного глючит. Если у вас возникнут проблемы, просто перезапустите Minecraft Pi и продолжайте как ни в чём не бывало. Sonic Pi позаботится о том, чтобы автоматически соедениться c Minecraft Pi.

## Требуется Raspberry Pi 2

Настоятельно рекомендуется, использовать Raspberry Pi 2, если вы хотите запускать Sonic Pi и Minecraft в одно и то же время - особенно если вы хотите использовать звуковые возможности Sonic Pi.

## Поддержка API

На данном этапе, Sonic Pi поддерживает базовые манипуляции блоками и игроком, подробно описанные в разделе 11.1. Поддержка обратных вызовов событий, вызванных взаимодействием игрока с миром, планируется в будущих релизах.

# 11.1 - Базовый API Minecraft Pi

Sonic Pi в настоящее время поддерживает следующие основные взаимосвязи с Minecraft Pi:

Отображение сообщений в чате Установка позиции пользователя Получение позиции пользователя Установка типа блока по заданным координатам Получение типа блока по заданным координатам

Давайте рассмотрим каждую из них по очереди.

## Отображение сообщений в чате

Давайте посмотрим, как легко управлять Minecraft Pi из Sonic Pi. Во-первых, убедись, что и Minecraft Pi, и Sonic Pi, открыты в одно и то же время, а также, что вы вошли в мир Minecraft и можете там передвигаться.

Просто наберите в пустом буфере Sonic Pi следующий код:

    mc_message "Hello from Sonic Pi"

Когда вы нажмёте кнопку Выполнить, вы увидите своё сообщение в окне Minecraft. Поздравляю, вы написали свой первый код в Minecraft! Это было просто, не так ли?

## Установка позиции пользователя

Теперь давайте попробуем немного магии. Телепортируем себя куда-нибудь! Наберите следующее:

    mc_teleport 50, 50, 50

Когда вы нажмёте Выполнить - бум! Вы мгновенно переноситесь на новое место. Скорее всего, это будет где-то в небе, и вы упадёте на землю, либо на сушу, или в воду. Что это за цифры: `50, 50, 50`? Это координаты места, в которыое вы пытаетесь телепортироваться. Давайте сделаем короткий перерыв, чтобы выяснить, что такое координаты и как они работают, потому что они очень, очень важны для программирования Minecraft.

## Координаты

Представьте пиратскую карту с большой `X` меткой на месте расположения каких-нибудь сокровищ. Точное местоположение `X` может быть описано с помощью двух чисел - как далеко по карте слева направо и как далеко по карте снизу вверх. Например `10см` по горизонтали и `8 см` вверх. Эти числа `10` и `8` - это координаты. Вы можете легко представить местоположение других тайников с сокровищами, описанное другой парой чисел. Возможно, есть большой сундук золота на `2` по горизонтали и `9` по вертикали…

Но, в Minecraft двух чисел не достаточно. Нам также нужно знать как высоко мы находимся. Следовательно, нам нужно три числа:

Как далеко с права на лево в мире - `x` Как далеко от передней до задней части мира - `z` Как высоко мы находимся в мире - `y`

Ещё один ньюанс - мы описываем эти координаты в таком порядке: `x`, `y`, `z`.

## Нахождение Твоих Текущих Координат

Давайте поиграем с координатами. Переместитесь в приятное место на карте Minecraft, а потом переключитесь на Sonic Pi. Введите следующее:

    puts mc_location

Когда вы нажмёте кнопку Выполнить вы увидите, что координаты текущего положения отобразятся в окне журнала. Запишите их, затем двигайтесь вперёд в мире Minecraft и попробуйте получить координаы снова. Обратите внимание, как они изменились! А сейчас, я рекомендую вам потратить некоторое время на повторение именно этого - немного переместитесь в мире, посмотрите координаты и повтори это снова. Делайте это до тех пор, пока не начнёте чувствовать, как изменяются координаты, когда вы перемещаетесь. Как только вы поймёте, как координаты работают, программирование с Minecraft API будет совершенной мелочью.

## Давайте Строить!

Теперь, когда вы знаете, как найти текущую позицию и телепортироваться, используя координаты, у вас есть все инструменты, чтобы начать строить различные вещи в Minecraft с помощью кода. Допустим, вы хочтите сделать блок с координатами `40`, `50`, `60` стеклянным. Это супер просто:

    mc_set_block :glass, 40, 50, 60

Ха-ха, это действительно было просто. Увидеть дело рук своих проще простого - телепортируйтесь рядом и посмотрите:

    mc_teleport 35, 50, 60

Теперь повернитесь и ты увидите свой стеклянный блок! Попробуйте изменить его на алмаз:

    mc_set_block :diamond, 40, 50, 60

Если вы смотрели в правильном направлении, то могли увидеть эти изменения соими глазами! Это начало чего-то захватывающего…

## Смотрим На Блоки

Давай рассмотрим ещё одну, последнюю вещь, прежде чем перейдём к чему-то немного более сложному. Задавая набор координат, можно указать какого типа должен быть блок. Давайте попробуем это с алмазным блоком, который мы только что создали:

    puts mc_get_block 40, 50, 60

Эй! Это `:diamond`. Попробуйте изменить его обратно на стекло и спросите Minecraft об этом снова - он ответит `:glass`? Я уверен, что да :-)

## Доступные Типы Блоков

Перед тем, как пойти неистово кодировать на Minecraft Pi, вы могли бы найти этот список доступных типов блоков полезным:

        :air
        :stone
        :grass
        :dirt
        :cobblestone
        :wood_plank
        :sapling
        :bedrock
        :water_flowing
        :water
        :water_stationary
        :lava_flowing
        :lava
        :lava_stationary
        :sand
        :gravel
        :gold_ore
        :iron_ore
        :coal_ore
        :wood
        :leaves
        :glass
        :lapis
        :lapis_lazuli_block
        :sandstone
        :bed
        :cobweb
        :grass_tall
        :flower_yellow
        :flower_cyan
        :mushroom_brown
        :mushroom_red
        :gold_block
        :gold
        :iron_block
        :iron
        :stone_slab_double
        :stone_slab
        :brick
        :brick_block
        :tnt
        :bookshelf
        :moss_stone
        :obsidian
        :torch
        :fire
        :stairs_wood
        :chest
        :diamond_ore
        :diamond_block
        :diamond
        :crafting_table
        :farmland
        :furnace_inactive
        :furnace_active
        :door_wood
        :ladder
        :stairs_cobblestone
        :door_iron
        :redstone_ore
        :snow
        :ice
        :snow_block
        :cactus
        :clay
        :sugar_cane
        :fence
        :glowstone_block
        :bedrock_invisible
        :stone_brick
        :glass_pane
        :melon
        :fence_gate
        :glowing_obsidian
        :nether_reactor_core