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 очень простой интерфейс для кодирования музыки. Мы потратим совсем немного времени на его изучение.

Интерфейс Sonic Pi

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

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).

I. Cue Viewer

All internal and external events (called cues in Sonic Pi) are automatically logged in the Cue Viewer. For example, if you have a MIDI controller connected and press one of its buttons, you’ll see a new cue event in the Cue Viewer telling you the name of the controller and which button you pressed. Once you’ve mastered the basics of making and producing sounds, you’ll start to want to cue sounds or whole sections of sounds based on events such as these. A cue event is just an indication that something happened. For example, every time a live loop spins round, it sends a cue event out which is logged in the Cue Viewer. Also, external events such as MIDI messages from connected MIDI equipment and OSC messages from other programs or computers are also displayed in the Cue Viewer. It is also possible to directly generate cue events using the cue function. Anything that appears in the Cue Viewer can be used to trigger something happening. This is covered in more detail in Sections 10 to 12 of this tutorial.


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

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

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

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

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

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

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


2 - Синтез

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

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

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


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

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

play 70

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

Звук!

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

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

play 75

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

play 60

So, lower numbers make lower pitched beeps and higher numbers make higher pitched beeps. Just like on a piano, the keys at the lower part of the piano (the left hand side) play lower notes and the keys on the higher part of the piano (the right hand side) play higher notes.

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

Now multiple sounds at the same time (by not sleeping between successive calls to play):

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.

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

Чтобы увидеть, какие синты есть в Sonic Pi, загляните во вкладку Synths в меню слева внизу (рядом с Fx). Там их больше 20 на выбор. Вот несколько моих любимых:

: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. прямую линию). Следующая диаграмма иллюстрирует такой переход:

release envelope

Вертикальная линия на левом краю диаграммы показывает, что звук начинается при амплитуде 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

ASR огибающая

Задержка полезна для важных звуков, которые вы хотели бы полностью выделить при сведении, прежде чем они перейдут в необязательную фазу затухания. Конечно же, совершенно допустимо устанавливать и 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

ADSR огибающая

Уровень спада (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

ASR огибающая

Можно, к тому же, устанавливать 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

ASR огибающая

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

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

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

С другой стороны, можно задействовать систему автодополнения. Просто начните набирать название группы сэмплов, например 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 для множества подробных примеров использования. Обратите внимание, что порядок фильтров соблюдается.

Композиции

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

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

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

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

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

choose

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

choose([60, 65, 72])

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

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

rrand

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

87.5054931640625 86.05255126953125 61.77825927734375

rrand_i

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

88 86 62

случайный

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

loop do
  play 60, amp: rand
  sleep 0.25
end

rand_i

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

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

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

one_in

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

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


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

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

==> Пропуск создания потока: thread, поток с именем :amen уже существует.

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 знал, что играть? Он просто вспомнил вашу функцию даже после её удаления из буфера. Он запомнил что вы напечатали. Это работает только с функциями, которые создаются при помощи definedefonce)

Параметризованные функции

Вам, возможно, будет интересно узнать, что вашу функцию можно научить принимать аргументы, прямо как 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

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

Внимание: переменные и потоки

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

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

В примере выше мы присвоили ряд чисел переменной ‘a’ и затем использовали её в двух отдельных ‘live_loop`s’. В первом живом цикле каждые ‘0,5’ секунды мы сортируем кольцевой список (1, 2, 3, 4, 5, 6), затем отображаем результат в журнале. Если ты запустишь код, ты увидишь, что выведенный список не всегда отсортирован!. Это может быть для тебя сюрпризом, ведь иногда список выводится отсортированным, а иногда нет. Это называется недетерминированным поведением и является результатом неприятной проблемы называемой гонкой состояний. Проблема заключается в том, что второй живой цикл также работает с нашим кольцевым списком (в данном случае перемешивает его) и на момент вывода на экран список может быть как отсортирован, так и перемешан. Оба живых цикла соревнуются сделать разные вещи с одной переменной и каждый раз ‘побеждает’ разный цикл.

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

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

Однако, иногда мы хотим поделиться чем-то между потоками. Например, текущей тональностью, BMP, синтом и т.д. В этом случае решением будет воспользоваться специальными потоко-безопасными состояниями системы Sonic Pi через функции ‘get’ и ‘set. Это будет осуждаться в разделе 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 в левом нижнем углу справочной системы. Вот некоторые из моих любимых:

колебание, реверберации, эхо, искажение, разрезание

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


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 нот.

Это настолько распространенный паттерн, что with_fx поддерживает опцию для выполнения именно этого, но без необходимости писать блок 16.times:

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

Обе записи: reps: 16 и 16.times do будут вести себя одинаково. Reps: 16 по сути повторяет код в блоке do / end 16 раз, так что вы можете использовать их оба взаимозаменяемо и выбрать тот, который вам удобнее.

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


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. Так же работают и параметризованные функции.

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


- Настройки плавного изменения состояния

Вы могли заметить, что есть множество настроек, имя которых оканчивается на _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

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

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

Один из вариантов - разместить все ноы в виде списка: [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

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


- Гаммы

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 внизу слева от этого учебника и затем выберите аккорд или гамму в списке. Прокручивайте вниз информацию в главной панели, пока не увидите длинный список аккордов или гамм (в зависимости от того, что вы ищете).

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


- Кольцевые списки

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

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

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 создает кольцо логических значений с Евклидовым распределением.

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


- Кольцевые цепи

Помимо конструкторов, таких как 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) - возвращает кольцо с результатами вызова .choose 3 раза .pick (3) - возвращает кольцо с результатами вызова .choose 3 раза .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) - возвращает новое кольцо все элементы которого умножены на 2 (если кольцо содержит только числа)

Конечно, цепные методы, принимающие числовые аргументы, могут принимать и другие числа! Так что не стесняйтесь вызывать .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

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


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

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

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 - Временное Состояние

Часто полезно иметь информацию, которая является общей для нескольких потоков или живых циклов. Например, тебе может понадобиться сделать общими значение текущей тональности, BMP или даже более отвлеченные понятия такие как текущая ‘сложность’ (которая может быть интерпретирована по-разному в разных потоках). Мы также не хотим при этом потерять имеющуюся у нас гарантию определенности. Другими словами, мы все еще хотели бы иметь возможность делиться кодом с другими и точно знать, что они услышат, когда запустят его. В конце Раздела 5.6 этого руководства мы кратко обсудили, почему мы не должны использовать переменные для обмена информацией между потоками чтобы не потерять фактор детерминизма (из-за гонки состояний).

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

Встречайте get и set


10.1 - Set и Get

Sonic PI имеет глобальное хранилище памяти, называемое Временным состоянием. В основном оно используется чтобы “установить” (set) информацию и “получить” (get) информацию. Давайте нырнем глубже…

Set

Чтобы хранить информацию во Временном Состоянии нам нужны две вещи:

информация, которую мы хотим сохранить, уникальное имя (ключ) для этой информации.

Например, мы можем захотеть сохранить число 3000 с ключом :intensity. Это можно сделать используя функцию set:

set :intensity, 3000

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

set :intensity, 1000
set :intensity, 3000

В примере выше, где мы сохранили оба числа под одним ключом, последний вызов set ‘побеждает’, поэтому число связанное с :intensity будет равно 3000, так как первый вызов ‘set’ эффективно перезаписан.

Get

Для извлечения информации из Временного Состояния нам просто нужен ключ, который мы использовали в set, в нашем случае это :intensity. Тогда нам просто нужно вызвать get[:intensity], результат которого выведем на экран:

print get[:intensity] #=> выведет 3000

Обратите внимание, что запросы get могут возвращать информацию, которая была записана в set в предыдущем запуске исполнения кода. После того, как часть информации была записана в set, она становится доступной до тех пор, пока она либо не будет переопределена (точно так же, как мы переопределили значение:intensity от 1000 к ` 3000`), либо Sonic Pi не будет закрыт.

Множество потоков выполнения

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

live_loop :setter do
  set :foo, rrand(70, 130)
  sleep 1
end
live_loop :getter do
  puts get[:foo]
  sleep 0.5
end

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

{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

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

Просто о системе детерминированных состояний

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

## Пример недетерминированного поведения
## (из-за гонки состояний, вызванной несколькими
## живыми циклами, манипулирующими одной и той же переменной
## в одно и то же время).
##
## Если вы запустите этот код, вы заметите
## что список, отображаемый в  журнале
## не всегда сортируется!
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

Давайте посмотрим, как это может выглядеть, используя get и set:

## Пример детерминированного поведения
## (несмотря на одновременный доступ к общему состоянию)
## используя новую систему Time State от Sonic Pi.
##
## Когда этот код выполняется, список,
## отображаемый в журнале, всегда отсортирован!
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

Обратите внимание, что этот код в значительной степени идентичен версии, использующей переменную. Однако когда вы запускаете код, он ведет себя так, как вы ожидаете с любым типичным кодом Sonic Pi - * он делает то же самое каждый раз * в этом случае благодаря системе Time State.

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


- Синхронизация

В разделе 5.7, при рассмотрении проблемы синхронизации потоков, были представлены функции cue и sync То, что там не было разъяснено, это система Time State, которая обеспечивает эту функциональность. Так случилось, что функцияset на самом деле является вариацией cue и устроена поверх той же базовой функциональности, которая заключается в сообщении информации системе Time State. Кроме того, функция sync также спроектирована таким образом, чтобы бесперебойно работать с Time State - любую информацию, которую мы планируем хранить в Time State, мы можем синхронизировать с ее помощью. Другими словами - * мы применяем функциюsync к событиям, которые еще только предстоит сообщить системе Time State *.

В ожидании событий

Давайте кратко рассмотрим, как использовать sync для ожидания новых событий, которым предстоит быть добавленными в Time State:

in_thread do
  sync :foo
  sample :ambi_lunar_land
end
sleep 2
set :foo, 1

В этом примере мы сначала создаем поток, который ожидает в дальнейшем добавления события : foo в Time State. После этого, мы “спим” 2 такта, а затем посредством функции setустанавливаем для : foo значение 1. Это определяет функцию sync, которая в следующей строке воспроизводит сэмпл: ambi_lunar_land.

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

Передача значений в будущее

В приведенном выше примере мы установили для : foo значение 1, с которым ничего не сделали. На самом деле мы можем получить это значение из sync, вызывающего поток:

in_thread do
  amp = sync :foo
  sample :ambi_lunar_land, amp: amp
end
sleep 2
set :foo, 0.5

Обратите внимание, что значения, которые передаются через set и cue, должны быть потокобезопасными - то есть кольца, числа, символы или замороженные строки не должны изменяться. Sonic Pi выдаст ошибку, если значение, которое вы пытаетесь сохранить в Time State, недопустимо.


- Сопоставление паттернов

При получении и установке информации в Time State можно использовать более сложные ключи, чем основные символы, такие как : foo и: bar. Вы также можете использовать строки в стиле URL, которые называются пути (paths), например " / foo / bar / baz ". Как только мы начнем работать с путями, мы сможем воспользоваться преимуществами реализованной в Sonic Pi сложной системы сопоставления паттернов для того, чтобы пользоваться функциями get и sync с похожими, а не с полностью идентичными путями. Давайте взглянем на это.

Сопоставление любого сегмента пути

Предположим, что мы хотим дождаться следующего события, которое имеет три сегмента пути:

sync "/*/*/*"

Это будет сопоставимо с любым событием Time State с тремя сегментами пути, независимо от их имен. Например:

cue "/foo/bar/baz" cue "/foo/baz/quux" cue "/eggs/beans/toast" cue "/moog/synths/rule"

Однако он * не будет * сопоставляться с путями с меньшим или большим количеством сегментов. Следующие пути не будут сопоставляться:

cue "/foo/bar" cue "/foo/baz/quux/quaax" cue "/eggs"

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

Сопоставление частичных сегментов

Если мы знаем, с чего начинается или заканчивается сегмент, мы можем использовать * в дополнение к частичному имени сегмента. Например: " / foo / b * / baz " будет соответствовать любому пути, который имеет три сегмента, первый из которых foo, последний baz, а средний сегмент может быть любым, начинающимся с b. Таким образом, с этим будут сопоставимы следующие пути:

cue "/foo/bar/baz" cue "/foo/baz/baz" cue "/foo/beans/baz"

Однако, не будут сопоставимы следующие пути:

cue "/foo/flibble/baz" cue "/foo/abaz/baz" cue "/foo/beans/baz/eggs"

Вы также можете поместить * в начале сегмента, чтобы указать последние символы сегмента: " / foo / * zz / baz ", который будет соответствовать любым 3 сегментам cue или set, где первый сегмент - foo, последний - baz, а средний сегмент заканчивается zz, например "cue" / foo / whizz / baz ".

Сопоставление вложенных сегментов пути

Иногда вы не знаете, сколько сегментов пути вы хотите сопоставить. В этих случаях вы можете использовать возможности двойной звезды: **, например " / foo / ** / baz ". Тогда это будет сопоставимо с:

cue "/foo/bar/baz" cue "/foo/bar/beans/baz" cue "/foo/baz" cue "/foo/a/b/c/d/e/f/baz"

Сопоставление отдельных букв

Вы можете использовать символ ? для сопоставления с одним символом. Например " /? оo / bar / baz ", что будет сопоставимо с:

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

Сопоставление из множества слов

Если вы знаете, что сегмент может быть представлен словом из заданного набора, вы можете использовать сопоставители { и }, чтобы указать список вариантов. Например `” / foo / {bar, beans, eggs} / quux “, что может быть сопоставлено только со следующим:

cue "/foo/bar/quux" cue "/foo/beans/quux" cue "/foo/eggs/quux"

Сопоставление из множества букв

Наконец, вы можете сопоставить сегмент из набора букв, если используете сопоставители [ и ], чтобы указать список вариантов. Например путь " / foo / [abc] ux / baz " будет сопоставим только с:

cue "/foo/aux/baz" cue "/foo/bux/baz" cue "/foo/cux/baz"

Вы также можете использовать символ - для указания диапазонов букв. Например, " / foo / [a-e] ux / baz "будет сопоставим только с:

cue "/foo/aux/baz" cue "/foo/bux/baz" cue "/foo/cux/baz" cue "/foo/dux/baz" cue "/foo/eux/baz"

Объединение сопоставителей

При вызове sync или get вы можете комбинировать сопоставители в любом порядке, который вы считаете подходящим для сопоставления любому событию Time State, заданному с помощью cue или set. Давайте рассмотрим потрясающий пример:

in_thread do
  sync "/?oo/[a-z]*/**/ba*/{quux,quaax}/"
  sample :loop_amen
end
sleep 1
cue "/foo/beans/a/b/c/d/e/bark/quux/"

Сопоставление паттернов по спецификации протокола OSC

Для тех, кому интересно, эти правила сопоставления основаны на спецификации сопоставления паттернов протокола Open Sound Control. Подробности описаны здесь: http://opensoundcontrol.org/spec-1_0


11 - MIDI

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

Иметь возможность преобразовывать действия в реальном мире в события Sonic Pi с помощью кода Иметь возможность использовать сильную временную модель и семантику Sonic Pi для управления и манипулирования объектами в реальном мире

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

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


11.1 - Прием MIDI-данных

В этом разделе мы узнаем, как подключить MIDI-контроллер для отправки событий в Sonic Pi для управления нашими синтезаторами и звуками. Хватай свою MIDI-клавиатуру или контроллер, и начнем работать физически!

Подсоединение MIDI контроллера

Чтобы получить информацию с внешнего MIDI-устройства в Sonic Pi, нам сначала нужно подключить ее к нашему компьютеру. Как правило, это происходит через USB порт, хотя старое оборудование будет иметь 5-контактный разъем DIN, для которого вам потребуется аппаратная поддержка вашего компьютера (например, некоторые звуковые карты имеют разъемы MIDI DIN). После подключения устройства запустите Sonic Pi и загляните в раздел IO на панели «Настройки». Вы должны увидеть там в списке ваше устройство. Если его нет, попробуйте нажать кнопку «Reset MIDI» и посмотреть, появится ли оно. Если вы по-прежнему ничего не видите, то попробуйте обратиться к конфигурации MIDI в вашей операционной системы, чтобы уточнить, доступно ли она ваше устройство там. В противном случае, не стесняйтесь задавать вопросы в публичном чате: http://gitter.im/samaaron/sonic-pi

Прием событий MIDI

Как только ваше устройство подключено, Sonic Pi будет автоматически получать от него события. Вы можете убедиться в этом сами, манипулируя вашим MIDI-устройством и поглядывая в регистратор сигналов в правом нижнем углу, под журналом (если его не видно, перейдите в «Настройки» -> «Редактор» -> «Показать/Скрыть» и включите «Показать журнал сигналов»). Вы увидите поток событий, таких как:

/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]

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

Временные состояние MIDI

Эти события разбиты на два раздела. Во-первых, есть имя события, например /midi:nanokey2_keyboard:0:1/note_on, а во-вторых, есть значения события, такие как [18, 62] . Интересно, что это две вещи, которые нам нужны для хранения информации в Time State. * Sonic Pi автоматически вставляет входящие события MIDI в Time State *. Это означает, что вы можете использовать get, чтобы получить последнее значение MIDI, а также использоватьsync для ожидания следующего MIDI значения, применяя все, что мы узнали в разделе 10 этого руководства.

Контролируя код

Теперь мы подключили MIDI-устройство, увидели его события в журнале и обнаружили, что наше знание Time State - это все, что нам нужно для работы с этими событиями, теперь мы можем начать веселиться. Давайте создадим простое MIDI-пианино:

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

В приведенном выше коде происходит несколько вещей, включая некоторые проблемы. Во-первых, у нас есть простой live_loop, который будет постоянно повторять код, выполняемый в блоке внутри ` do / end. Это было дано разъяснение в Разделе 9.2. Во-вторых, мы применяем sync для ожидания следующего подходящего для сопоставления события Time State. Мы используем строку, определяющую MIDI-сообщение, которое мы ждем (и которое совпадает с отображением в журнале событий). Обратите внимание, что эта длинная строка пдставояется вам системой автозаполнения Sonic Pi, так что вам не нужно печатать все вручную. В журнале мы увидели, что для каждого MIDI note on события было два значения, поэтому мы присваиваем результат двум отдельным переменным note и velocity. Наконец, мы запускаем синтезатор : piano`, передавая ему нашу ноту.

Теперь попробуйте сами. Введите приведенный выше код, замените ключ синхронизации строкой, соответствующей вашему конкретному MIDI-устройству, и нажмите Выполнить. Вуаля, у вас есть пианино! Однако вы, вероятно, заметите пару проблем: во-первых, все ноты имеют одинаковую громкость независимо от того, как сильно вы нажимаете на клавиатуру. Это можно легко исправить преобразовав значение MIDI velocity в амплитуду звукового сигнала. Учитывая, что MIDI имеет диапазон 0-> 127, чтобы преобразовать это число в значение между 0-> 1, нам просто нужно разделить его на 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

Обновите код и снова нажмите «Выполнить». Теперь зависимость громкости от скорости нажатия клавиш на клавиатуре соблюдается. Далее, давайте избавимся от этой досадной паузы.

Устранение задержки

Прежде чем мы сможем убрать эту паузу, нам нужно знать, почему она возникает. Чтобы обеспечить своевременную синхронизацию всех синтезаторов и эффектов на различных процессорах с различными возможностями, Sonic Pi по умолчанию планирует запуск аудио *заранее * на 0,5 секунды. (Обратите внимание, что эта дополнительная задержка может быть настроена через fns set_sched_ahead_time! и use_sched_ahead_time). Эта задержка 0,5 секунды добавляется и к нашим триггерам синтезатора : piano, поскольку она добавляется ко всем синтезаторам, запускаемым Sonic Pi. Как правило, мы действительно хотим добавить дополнительную задержку, поскольку это означает, что все синтезаторы будут рассчитаны вовремя. Однако это имеет смысл только для синтезаторов, запускаемых кодом с использованием play и sleep. В нашем случае мы фактически запускаем синтезатор : piano с помощью внешнего MIDI-устройства и поэтому не хотим, чтобы Sonic Pi контролировал время за нас. Мы можем отключить эту задержку с помощью команды use_real_time, которая отключает задержку для текущего потока. Это означает, что вы можете использовать режим реального времени для живых циклов, чье время контролируется путем синхронизации с внешними устройствами, и сохранять задержку по умолчанию для всех других живых циклов. Давайте взглянем на это:

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

Обновите код, чтобы он соответствовал приведенному выше, и снова нажмите «Выполнить». Теперь у нас есть пианино с низкой задержкой и переменной скоростью, кодируемое всего за 5 строк. Это было не так уж и просто!

Получение значений

Наконец, поскольку наши MIDI-события идут прямо в Time State, мы также можем использовать функцию get для получения последнего значения. Это не блокирует текущий поток и не возвращает nil, если не найдено никакого значения (которое вы можете переопределить, передав значение по умолчанию - смотрите документацию по get). Помните, что вы можете вызвать get в любом потоке в любое время, чтобы увидеть последнее соответствующее значение Time State. Вы даже можете использовать time_warp, чтобы вернуться назад во времени, вызвать get и увидеть прошедшие события …

Теперь контролируете Вы

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


11.2 - MIDI Out

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

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

Также есть много других поддерживаемых MIDI-сообщений - ознакомьтесь с документацией API для остальных функций, начинающихся с midi_.

Подсоединение MIDI-устройств

Чтобы отправить MIDI-сообщение на внешнее устройство, мы должны сначала подключить его. Ознакомьтесь с подразделом «Подключение MIDI-контроллера» в разделе 11.1 для получения более подробной информации. Обратите внимание, что если вы используете USB, подключение к устройству, на которое вы отправляете сообщение (а не получаете от него), является той же процедурой. Однако, если вы используете классические DIN-разъемы, убедитесь, что вы подключены к MIDI-выходу вашего компьютера. Вы должны увидеть ваше MIDI-устройство в списке в панели настроек.

Отправка MIDI событий

Многие midi_ * функции работают так же, как play, sample и synth, так как они отправляют сообщение в текущее (логическое) время. Например, чтобы распределить вызовы функций midi_ * , вам нужно использовать sleep, как вы это делали с play. Давайте взглянем:

midi_note_on :e3, 50

Это отправит событие MIDI-note on на подключенное MIDI-устройство со скоростью нажатия клавиши 50. (Обратите внимание, что Sonic Pi автоматически преобразует ноты в форме : e3 в соответствующий им номер MIDI, например, 52)

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

midi_note_off :e3

Выбор MIDI-устройства

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

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

midi_note_on :e3, port: "moog_minitaur"

Мы также можем указать канал для отправки посредством опции channel: (используя значение в диапазоне 1-16):

midi_note_on :e3, channel: 3

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

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

MIDI студия

Наконец, действительно забавная вещь - подключить аудиовыход вашего MIDI-синтезатора к одному из аудиовходов вашей звуковой карты. Тогда вы сможете управлять синтезатором с помощью кода посредством функций midi_ *, а также манипулировать звуком с помощью live_audio и 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

(Функция midi доступна в виде удобных сокращений для отправки событий note on и note off одной командой. Для получения дополнительной информации ознакомьтесь с документацией).


12 - OSC

В дополнение к MIDI, другой способ получать и выводить информацию из Sonic Pi, но уже через сеть, предполагает использование простого протокола OSC - Open Sound Control. Это позволит вам обмениваться сообщениями с внешними программами (как работающими на вашем компьютере, так и на других компьютерах), что открывает потенциальные возможности для контроля за пределами протокола MIDI, который имеет ограничения из-за его дизайна 1980-х годов.

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


12.1 - Получение сообщений через протокол OSC

По умолчанию при запуске Sonic Pi он прослушивает порт 4560 для входящих сообщений OSC от программ на том же компьютере. Это означает, что без какой-либо дополнительной настройки вы можете отправить Sonic Pi сообщение OSC, и оно будет отображаться в журнале событий, как и входящие MIDI-сообщения. Любое входящее сообщение OSC автоматически добавляется в Time State, и вы можете использовать get и sync для работы с входящими данными - как с MIDI или синхронизацией live_loops - см. Разделы 5.7 и 10.2. Вспомним, как это работает.

Простой OSC-слушатель

Давайте создадим простой OSC-слушатель:

live_loop :foo do
  use_real_time
  a, b, c = sync "/osc*/trigger/prophet"
  synth :prophet, note: a, cutoff: b, sustain: c
end

В этом примере мы синхронизируем путь OSC, который описали как "/osc*/trigger/prophet". Это может быть любой допустимый путь OSC (все буквы и цифры поддерживаются, а / используется, как и в URL-адресации, для разбиения пути на несколько слов). Префикс / osc добавляется Sonic Pi ко всем входящим сообщениям OSC, поэтому нам нужно отправить сообщение OSC с путем / trigger / prophet, чтобы вызванная нами функция sync запустила синтезатор prophet.

Отправка OSC в Sonic Pi

Мы можем отправить OSC в Sonic Pi с любого языка программирования, который имеет библиотеку OSC. Например, если мы отправляем OSC из Python, мы можем сделать что-то вроде этого:

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])

Или, если мы отправляем OSC из Clojure, мы можем сделать что-то вроде этого из REPL:

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

Получение данных от удаленных машин

Из соображений безопасности, по умолчанию Sonic Pi не позволяет удаленным машинам отправлять ему OSC-сообщения. Однако вы можете включить поддержку удаленных машин в Настройки-> IO-> Сетевой OSC-> Принимать удаленные сообщения OSC. Как только вы включите это, вы сможете получать сообщения OSC с любого компьютера в вашей сети. Обычно отправляющему устройству необходимо знать ваш IP-адрес (уникальный идентификатор вашего компьютера в вашей сети - например, номер телефона или адрес электронной почты). Вы можете узнать IP-адрес своего компьютера, посмотрев раздел IO на панели настроек. (Если ваш компьютер имеет более одного IP-адреса, при наведении курсора мыши на указанный адрес появится список всех известных адресов).

Обратите внимание, что некоторые программы, такие как TouchOSC для iPhone и Android, поддерживают отправку OSC в качестве стандартной функции. Так, включив опцию прослушивания входящих сообщений от удаленных машин и зная свой IP-адрес, вы можете мгновенно начать отправку сообщений из приложений, вроде TouchOSC, которые позволяют создавать собственные сенсорные элементы управления с помощью слайдеров, кнопок, валкодеров и т. Д. Это может предоставить вам огромный диапазон вариантов ввода управляющих данных.


12.2 - Отправка OSC

В дополнение к получению OSC и работе с ним, используя Time State, мы также можем отправлять сообщения OSC одновременно с музыкой, исполняемой посредством нашего кода (точно так же, как мы можем одновременно с этим отправлять и MIDI-сообщения). Нам просто нужно знать, на какой IP-адрес и порт мы отправляем. Давайте попробуем:

use_osc "localhost", 4560
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:127.0.0.1:4560/hello/world. (Notice how Sonic Pi automatically prefixes all incoming OSC messages with /osc and then the hostname and port of the sender.)

Отправка OSC в другие программы

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

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

В этом случае мы предполагаем, что есть другая программа на том же компьютере, которая прослушивает порт 123456. Если это так, то она получит сообщение OSC “/ hello / world`, с которым она сможет сделать все, что захочет.

Если наша программа работает на другом компьютере, нам нужно знать ее IP-адрес, который мы используем вместо " localhost ":

use_osc "192.168.10.23", 123456
osc "/hello/world"

Теперь мы можем отправлять сообщения OSC на любое доступное нам устройство через наши локальные сети и даже через Интернет!


13 - Многоканальное аудио

До сих пор, с точки зрения звукового производства, мы исследовали запуск синтезаторов и записанных звуков через функции play, synth и sample. Затем они генерировали звук, который воспроизводился через нашу стерео систему. Тем не менее, многие компьютеры также имеют возможность ввода звука, например, через микрофон, в дополнение к возможности отправлять звук на более чем две колонки. Часто эта возможность становится доступной благодаря использованию внешней звуковой карты (существуют устройства для всех платформ). В этом разделе руководства мы рассмотрим, как мы могли бы использовать преимущества этих внешних звуковых карт и без усилий работать в Sonic Pi с несколькими каналами входящего и исходящего аудио.


13.1 - Аудио вход

Одним простым (и, должно быть, уже знакомым) способом доступа к аудио входам является использование нашего друга synth с указанием для него пути : sound_in:

synth :sound_in

Это будет работать так же, как и любой синтезатор, такой как «synth: dsaw», за исключением того, что сгенерированный звук будет считываться непосредственно с первого входа звуковой карты вашей системы. На ноутбуках это обычно встроенный микрофон, но если у вас есть внешняя звуковая карта, вы можете подключить любой аудиовход к первому входу.

Увеличение длительности

Одна вещь, которую вы могли бы заметить, это то, что как synth: dsaw, синтезатор: sound_in длится всего 1 такт, поскольку к нему применяется стандартная огибающая. Если вы хотите, чтобы он звучал немного дольше, измените настройки огибающей ADSR. Например, следующий код будет ближайшие 8 тактов держать открытым аудиовход для нашего синтезатора:

synth :sound_in, sustain: 8

Добавление эффектов

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

with_fx :reverb do
  with_fx :distortion do
    synth :sound_in, sustain: 8
  end
end

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

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

with_fx :distortion do
  synth :sound_in, sustain: 8
end
with_fx :reverb do  
  synth :sound_in, sustain: 8
end

Многоканальный вход

Вы можете выбрать, какой аудиовход вы хотите воспроизвести, с помощью опции input:. Вы также можете указать стереовход (два последовательных входа), используя синтезатор : sound_in_stereo. Например, если у вас есть звуковая карта с по крайней мере тремя входами, вы можете рассматривать первые два как стереопоток и добавлять искажения, а третий - как монопоток и добавлять реверберацию со следующим кодом:

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

Потенциальные сложности

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


13.2 - Живое аудио

Синтез : sound_in, как описано в предыдущем разделе, предоставляет очень гибкий и знакомый метод для работы с входящим аудио. Однако, как уже говорилось, у него есть несколько проблем при работе с отдельным аудио входом в смысле отдельного инструмента (например, вашего голоса или гитары). Безусловно, лучший подход к работе с отдельным непрерывным аудиопотоком - использовать live_audio.

Именованный аудиовход

live_audio разделяет с live_loopпару основных ограничений, связанных с дизайном ядра Sonic Pi (отсюда и похожее имя). Во-первых, каждый объект такого типа должен иметь уникальное имя. Во-вторых, в любой момент времени может существовать только один поток live_audio с таким именем. Давайте взглянем:

live_audio :foo

Этот код будет действовать подобно synth: sound_in с некоторыми ключевыми отличиями: он работает постоянно (пока вы явно его не остановите), и вы можете перемещать его в новые FX-контексты динамически.

Работа с эффектами

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

with_fx :reverb do
  live_audio :foo
end

Однако, учитывая, что live_audio работает постоянно (по крайней мере, до тех пор, пока вы его не остановите), нас сильно бы ограничило, если, как и уже известные вам обычные синтезаторы, живой аудио поток так же был бы связан с эффектом : reverb все время своей работы. К счастью, это не тот случай, и эта функция была разработана так, чтобы было легко перемещаться между различными FX. Давай попробуем. Запустите приведенный выше код, чтобы услышать живой звук, поступающий непосредственно с первого входа вашей звуковой карты. Обратите внимание, что если вы используете ноутбук, это, как правило, ваш встроенный микрофон, поэтому рекомендуется использовать наушники, чтобы пресечь обратную связь между микрофоном и динамиками.

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

with_fx :echo do
  live_audio :foo
end

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

with_fx :reverb do
  with_fx :echo do
    live_audio :foo
  end
end

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

Остановка живого аудио

В отличие от стандартных синтезаторов, к live_audio не применяется огибающая, поэтому он будет работать постоянно (даже если вы удалите код, точно так же, как функция все еще определена в памяти, даже если вы удалите код в редакторе). Чтобы остановить его, вам нужно использовать аргумент : stop :

live_audio :foo, :stop

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

live_audio :foo

Кроме того, все запущенные живые звуковые потоки останавливаются, когда вы нажимаете глобальную кнопку «Стоп» (это работает и для всех других исполняемых синтезаторов и эффектов).

Стерео вход

Что касается аудиоканалов, то по умолчанию live_audio работает аналогично синтезатору: sound_in в том смысле, что он принимает отдельный монофонический входной аудио поток и преобразует его в стереопоток, используя заданное панорамирование. Однако, как и в случае : sound_in_stereo, можно также указать live_audio, читать два последовательных аудиовхода и обрабатывать их напрямую как левый и правый каналы. Это достигается через опцию : stereo. Например, чтобы обрабатывать вход 2 как левый канал, а вход 3 - как правый канал, необходимо указать опции input: значение 2 и включить стереорежим следующим образом:

live_audio :foo, stereo: true, input: 2

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


13.3 - Аудио выход

До сих пор в этом разделе мы рассматривали, как получить несколько потоков аудио в Sonic Pi - это возможно либо с помощью синтезатора : sound_in, либо с помощью мощной системы live_audio. В дополнение к работе с несколькими потоками входного аудио, Sonic Pi также может выводить несколько аудио потоков. Это достигается с помощью FX-контектса : sound_out .

Выходные контексты

Давайте быстро вспомним, как синтезаторы и эффекты в Sonic Pi выводят свое аудио в текущий контекст FX. Рассмотрим следующее:

with_fx :reverb do    # C
  with_fx :echo do    # B
    sample :bd_haus   # A
  end
end

Самый простой способ понять, что происходит с аудиопотоком, - это начать с аудио контекста, находящегося ближе всего к центру блока, и двигаться от него наружу. В этом случае самый внутренний контекст, представляющий собой исполняемый сэмпл: bd_haus, пометим как A. Аудио из него идет напрямую в его контекст, который назовем B - это эффект: echo. Это добавляет эхо к входящему аудио и выводит его в его контекст C - эффект : reverb. Затем к входящему потоку аудио добавляется реверберация и он выводится в контекст, который является самым верхним уровнем - это левый и правый динамики (выходы 1 и 2 на вашей звуковой плате). Аудио движется от начала до выхода на динамики, будучи на всем протяжении стереофоническим потоком.

Аудио выход FX

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

with_fx :reverb do      # C
  with_fx :sound_out, output: 3 do # B
    sample :bd_haus     # A
  end
end

В этом примере наш сэмпл : bd_haus выводит свое аудио во внешний контекст, который является FX-контекстом : sound_out. Это в свою очередь выводит звук далее во внешний FX-контекст : reverb (как и ожидалось). Однако он * также * выводит монофонический микс на 3-й выход звуковой карты системы. Поэтому звук, сгенерированный внутри : sound_out, имеет два назначения - FX-контекст : reverb и выход звуковой карты 3.

Моно и стерео выходы

Как мы уже видели, по умолчанию FX-контекст : sound_out выводит монофонический микс стереовхода на определенный канал в дополнение к передаче стереофонического канала во внешний контекст (как и ожидалось). Если вывод моно микса не совсем то, что вы хотите сделать, есть ряд альтернативных вариантов. Во-первых, используя опцию mode:, вы можете задать вывод только левого или только правого входного сигнала на звуковую карту. Или вы можете использовать FX-контекст : sound_out_stereo для вывода аудио на два последовательных выхода звуковой карты. Смотрите документацию функций для получения дополнительной информации и примеров их работы.

Прямой выход

Как мы также видели, поведение по умолчанию для : sound_out и: sound_out_stereo заключается в отправке аудио как во внешний контекст (что типично для всех эффектов), так и * на указанный выход на вашей звуковой карте. Однако иногда вам может потребоваться * только * отправить аудио на выход звуковой карты, а не во внешний контекст (, следовательно, без микширования и передачи аудио на стандартные выходные каналы 1 и 2). Это возможно при использовании стандартной опции FX-контекста amp:, который работает с аудио *после того, как FX-контекст смог бы на это аудио повлиять:

with_fx :sound_out, output: 3, amp: 0 do # B
  sample :loop_amen                      # A
end

В приведенном выше примере сэмпл : loop_amen отправляется во внешний FX-контекст : sound_out . Затем он отправляет монофонический микс на выход 3 звуковой карты, а затем умножает звук на 0, что, по сути, приводит к его отключению. Именно этот заглушенный сигнал затем отправляется во внешний контекст : sound_out, который является стандартным выходом. Поэтому с этим кодом выходные каналы по умолчанию не будут принимать никакого звука, а 3-й канал получит монофонический микс из amen drum break.


- Заключение

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

Если у вас есть какие-либо вопросы, которые не были рассмотрены в этом руководстве, переходите на [форумы Sonic Pi] (http://groups.google.com/group/sonic-pi/) и задавайте свои вопросы там. Вы обязательно найдете там кого-нибудь, кто дружелюбно протянет вам руку помощи.

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

Так что играйте, веселитесь, делитесь своим кодом, выступайте для друзей, показывайте свои экраны и помните:

Здесь нет ошибок, только возможности.

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. Лайвкодинг

Лучший способ начать быстро экспериментировать и исследовать 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. А находящийся на стенде диджея не крутит диски, — он пишет и редактирует код. Вживую. Это лайвкодинг.

Sam Aaron Live Coding

Это может звучать как притянутая за уши история из футуристичного ночного клуба, но кодирование музыки - это развивающийся тренд, часто называемый Лайвкодинг (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 растянуть (или сжать) сэмпл согласно установленнму количеству ударов.

Функции sample и synth в Sonic Pi дают вам контроль через необязательные параметры, такие как 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: вы слышите так много резонанса, что он начинает звучать сам по себе!

Наконец, для резкого изменения тембра попробуйте изменить параметр wave: на 1. Это выбор формы волны исходного генератора. Значение по умолчанию - 0 - пилообразная волна, 1 - прямоугольная волна, и 2 - треугольная форма волны.

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

Деконструирование TB-303

Конструкция оригинальных TB-303 на самом деле довольно проста. Как вы можете видеть из следующей диаграммы, главных составляющих всего 4.

TB-303 Design

Первой является волновой регенератор - сырая основа звука. В этом примере у нас прямоугольная волна. Дальше идёт генератор амплитудной огибающей, который контролирует амплитуду прямоугольной волны во времени. Он доступен в 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! Ну как, это было легко? Теперь, прекратите на мгновение чтение этой статьи и поиграйте с вашими собственными сообщениями. Веселитесь!

Screen 0

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!"

Screen 1

Магические блоки

Сейчас, когда вы нашли хорошее место, начнём строительство. Вы могли бы делать то, к чему привыкли, и начать яростно кликать мышкой, располагая блоки под курсором. Или вы могли бы использовать магию 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. Разве это не весело?

Соединим всё вместе

Screen 2

Давайте объединим всё, что мы видели до сих пор, с небольшой дополнительной магией. Совместим наши способности к телепортации с размещением блоков и музыкой, сделав музыкальное видео 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 год. Композитор Бизе как раз закончил свою последнюю оперу “Кармен”. К сожалению, как и множество других прогрессивных, ломающих стереотипы музыкальных произведений, публика поначалу её не приняла, ведь она была слишком дерзкой и непохожей на другие оперы того времени. Печально, но Бизе умер за десять лет до того, как эта опера возымела ошеломляющий международный успех и стала одной из самых известных и часто исполняемых опер всех времён. Из сочувствия к этой трагедии, возьмем одну из главных тем оперы “Кармен”, и преобразуем её в современный формат музыки, который также слишком возмутителен и чужд большинству людей нашего времени - кодированную музыку!

Расшифровка Хабанеры

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

Habanera Riff

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

Ноты

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

Мы уже знаем, как изменить высоту ноты в Sonic Pi - либо используя цифры, такие как play 75 и play 80, либо используя названия нот: play :Е и play :F. К счастью, каждой вертикальной позиции музыкальной партитуры соответствует определенная нота. Взгляните на эту удобную таблицу:

Notes

Паузы

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

Если вы внимательно посмотрите на партитуру, вы увидите, что это на самом деле сочетание горизонтальных линий с черными точками, которые представляют собой ноты, которые нужно играть, и волнистых штук, которые представляют собой паузы. К счастью, Sonic Pi имеет очень удобное представление для пауз: :r, так, если мы выполним: play :r, он на самом деле сыграет тишину! Мы могли бы также написать play :rest, play nil или play false - это всё эквивалентные способы представления пауз.

Ритм

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

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

Habanera Riff 2

Повторное кодирование Хабанеры

Теперь мы в состоянии начать переводить эту басовую партию для 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-виджеями

Screen 0

Все вы играли в 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. Теперь нажмите “Выполнить” снова. Эй! Всё изменилось без остановки кода. Это и есть та самая дверь к выступлениям в роли виджея. Продолжайте тренироваться и что-нибудь изменять. Насколько разнообразными можно сделать визуальные эффекты, не останавливая кода?

Эпические блочные структуры

Screen 1

Наконец, еще один отличный способ создания интересных визуальных эффектов - генерировать огромные повторяющиеся стены, парящие рядом. Для этого эффекта нам нужно перейти от размещения блоков случайным образом, к размещению их в упорядоченном виде. Мы можем сделать это с помощью двух вложенных итераций (нажмите кнопку “Помощь”, чтобы перейти в раздел 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, сделайте это реальностью. Когда вы достаточно попрактикуетесь, приглушите свет и покажите шоу своим друзьям!


- Серфинг случайных потоков

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

Там нет случайного

Первое, что можно узнать, что может вас удивить, играя с функциями рандомизации в Sonic Pi, это то, что они на самом деле не случайны. Что это на самом деле означает? Что ж, давайте предпримем пару эксперементов. Во-первых, представьте число в вашей голове от 0 до 1. Держите его там и не говорите мне. Теперь позвольте мне догадаться … это было 0.321567? Нет? Ба, да я явно не хорош в этом. Позвольте мне еще раз, но теперь давайте попросим Sonic Pi выбрать это число. Запустите Sonic Pi v2.7 + и укажите выбрать случайное число, но не говорите мне его:

print rand

Вскроем карты … было ли это 0.75006103515625? Да! Ха, я вижу, вы настроены немного скептически. Возможно, это была просто удачная догадка. Давай еще раз попробуем. Нажмите кнопку Выполнить еще раз и посмотрите, что мы получим … Что? 0.75006103515625 снова? Это явно не может быть случайным! Ты прав, это не так.

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

Случайная мелодия

Когда Sonic Pi загружается, он фактически загружает в память последовательность из 441 000 предварительно сгенерированных случайных значений. Когда вы вызываете случайную функцию, такую как rand или rrand, этот случайный поток используется для генерации вашего результата. Каждый вызов случайной функции берет значение из этого потока. Поэтому 10-й вызов случайной функции будет использовать 10-е значение из потока. Кроме того, каждый раз, когда вы нажимаете кнопку Выполнить, для этого цикла исполнения кода, поток случайных значений сбрасывается к своему началу. Вот почему я мог предсказать результат rand и почему «случайная» мелодия всегда была одинаковой. В каждой версии Sonic Pi используется один и тот же случайный поток, что очень важно, когда мы начинаем делиться друг с другом своими произведениями.

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

8.times do
 play rrand_i(50, 95)
 sleep 0.125
end

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

Удобства функций рандомизации

Sonic Pi поставляется с рядом полезных функций для работы со случайным потоком. Вот список некоторых из самых полезных:

rand - просто возвращает следующее значение в случайном потоке rrand - возвращает случайное значение в диапазоне rrand_i - возвращает случайное целое число в диапазоне one_in - возвращает true или false с заданной вероятностью dice - имитирует бросание костей и возвращает значение от 1 до 6 choose - выбирает случайное значение из списка

Ознакомьтесь с документацией этих функций в справочной системе для получения подробной информации и примеров использования.

Сброс потока

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

Мы можем вручную установить поток с помощью функции use_random_seed. В информатике случайное начальное число является отправной точкой, из которой может вырасти и расцвести новый поток случайных значений. Давай попробуем:

use_random_seed 0
3.times do
  play rrand_i(50, 95)
  sleep 0.125
end

Отлично, так мы получаем первые три ноты нашей случайной мелодии: 84, 83 и 71. Однако теперь мы можем изменить семя для чего-то другого. Как насчет этого:

use_random_seed 1
3.times do
  play rrand_i(50, 95)
  sleep 0.125
end

Интересно, что мы получили 83, 71 и 61. Вы можете заметить, что первые два числа здесь такие же, как и последние два числа из тех, что мы получили ранее. И это не совпадение.

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

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

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

Теперь, пока он все еще играет, измените начальное значение с 0 на другое. Попробуйте 100, или даже 999. Попробуйте свои собственные значения, поэкспериментируйте с этим - посмотрите, какое семя создает риф, который вам больше нравится.

Соединим всё вместе

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

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

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

- Управление вашим звуком

До сих пор в этой серии мы фокусировались на запуске звуков. Мы обнаружили, что можем запускать синтезаторы Sonic Pi с помощью play или synth, а предварительно записанные сэмплы с помощью sample. Мы также рассмотрели, как обернуть эти звуки внутрь FX-контекста студийных эффектов, таких как реверберация и искажение, используя команду with_fx. Объединив это с невероятно точной системой синхронизации Sonic Pi, вы сможете создавать огромное количество звуков, битов и риффов. Однако, как только вы тщательно выбрали параметры определенного звука и запустили его, у вас не будет возможности поиграть с ним, пока он воспроизводится, правильно? Неправильно! Сегодня вы узнаете кое-что очень мощное - как управлять работой синтезаторов.

Основной звук

Давайте создадим простой звук. Запустите Sonic Pi и в свободном буфере наберите следующее:

synth :prophet, note: :e1, release: 8, cutoff: 100

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

Узлы синтезатора

Малоизвестная особенность Sonic Pi заключается в том, что функции play, synth и sample возвращают нечто, называемое SynthNode, что представляет собой исполняемый звук. Вы можете захватить один из этих SynthNode, используя стандартную переменную, а затем ** контролировать ** ее в более поздний момент времени. Например, давайте изменим значение параметр cutoff:` после 1 такта:

sn = synth :prophet, note: :e1, release: 8, cutoff: 100
sleep 1
control sn, cutoff: 130

Давайте рассмотрим каждую строку по очереди:

Сначала мы запускаем синтезатор : prophet, используя функцию ` synth как обычно. Кроме того, мы еще фиксируем это в переменной с именем sn. Мы могли бы назвать эту переменную как-то иначе, например, «synth_node» или «jane» - имя не имеет значения. Однако полезно выбрать такое имя, которое будет что-то означать для вас и для людей, читающих ваш код. Я выбрал sn`, так как это мнемонически удобное сокращение для узла синтезатора (synth node).

В строке 2 у нас есть стандартная команда sleep. В этом нет ничего особенного - она просто просит компьютер подождать 1 такт, прежде чем перейти к следующей строке.

В строке 3 начинается веселье управления. Здесь мы используем функцию control, чтобы указать исполняемому SynthNode изменить значение среза фильтра на 130. Если вы нажмете кнопку ** Выполнить **, вы услышите, как синтезатор : prophet начнет воспроизводиться, как было прежде, но после 1 такта он будет звучать намного ярче.

Модулируемые параметры

Большинство параметров синтезаторов и эффектов в Sonic Pi могут быть изменены в процессе исполнения. Но это не относится ко всем из них. Например, параметры огибающей attack:, decay:, Sustain: и release: могут быть установлены только при запуске исполнения синтезатора. Выяснить, какие параметры можно, а какие нельзя изменять достаточно просто - перейдите к документации синтезатора или эффекта, а затем прокрутите вниз до спецификаций отдельных параметров, ориентируясь на фразы «Может быть изменено во время игры» или «Не может быть измененным после установки». Например, документация для : beep synth’s указывает, что параметр ‘attack:`изменять нельзя:

Default: 0 Должно быть больше или равно нолю Не может быть изменено после установки Масштабируется относительно текущего значения BPM

Множественные изменения

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

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

В этом фрагменте кода мы только добавили пару дополнительных вещей. Сначала мы определили новую переменную с именем notes, которая содержит ноты, которые мы хотели бы циклически перемещать (арпеджиатор - это просто причудливое имя для чего-то, что циклически перебирает список нот по порядку). Во-вторых, мы заменили наш одиночный вызов на control итерацией, вызывающей его 16 раз. В каждом вызове control мы проходим с помощью ` .tick наше кольцо notes, которое будет автоматически повторяться, как только мы доберемся до конца (благодаря невероятной силе колец Sonic Pi). Для некоторого разнообразия попробуйте заменить .tick на .choose` и посмотрите, можете ли вы услышать разницу.

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

control sn, note: notes.tick, cutoff: rrand(70, 130)

Плавные изменения

Когда мы контролируем SynthNode, он реагирует точно вовремя и мгновенно меняет текущее значение параметра на новое, как если бы вы нажали кнопку или щелкнули переключателем, запрашивая изменение. Это может звучать ритмично и резко - особенно если парамметр контролирует какой-нибудь аспект тембра, как , например, cutoff:. Однако иногда вы не хотите, чтобы изменения произошли мгновенно. Вместо этого вы можете плавно перейти от текущего значения к новому, как если бы вы переместили слайдер или валкодер. Конечно, Sonic Pi также может сделать это посредством _slide:.

Каждый параметр, который можно изменить, также имеет специальный соответствующий ему параметр _slide:, который позволяет указать время скольжения. Например, amp: имеет amp_slide:, так же как cutoff: имеет cutoff_slide:. Эти параметры скольжения работают немного иначе, чем все остальные, в том смысле, что они сообщают синтезатору, как себя вести **во время, когда ими управляют **. Давайте взглянем:

sn = synth :prophet, note: :e1, release: 8, cutoff: 70, cutoff_slide: 2
sleep 1
control sn, cutoff: 130

Обратите внимание, что этот пример точно такой же, как и раньше, за исключением добавления cutoff_slide:. Это говорит о том, что во время когда параметр cutoff: этого синтезатора будет управляться, потребуется 2 такта на то, чтобы перейти от текущего значения к новому. Поэтому, когда мы используем control, вы можете услышать скольжение значения среза фильтра от 70 до 130. Это создает интересное динамическое ощущение звука. Теперь попробуйте изменить время cutoff_slide: на более короткое значение, такое как 0,5, или более длинное значение, такое как 4, чтобы увидеть, как это меняет звук. Помните, что вы можете перемещать любые изменяемые параметры точно таким же образом, и каждое значение _slide: может быть совершенно разным. Вы можете одновременно медленно скользить по срезу фильтра, быстро смещать амплитуду и плавно двигаться по панораме со средней между этими значениями скоростью, ища для себя творческие новые возможности …

Соединим всё вместе

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

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

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

- Трекинг ритма

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

Счетчик тактов

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

Давайте поиграем - чтобы сдвинуть такт во времени, нам просто нужно вызвать tick. Откройте свободный буфер, введите следующий текст и нажмите Выполнить:

puts tick #=> 0

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

puts tick #=> 0
puts tick #=> 1
puts tick #=> 2

Всякий раз, когда вы видите символ # => в конце строки кода, это означает, что эта строка будет записывать в журнал текст, расположенный справа от этого символа. Например, put foo # => 0 означает, что код puts foo, напечатает 0 в журнале.

Проверка такта

Мы видели, что tick делает две вещи. Он увеличивает (+1) и возвращает нам значение текущего такта. Иногда мы просто хотим посмотреть текущий такт, не увеличивая его. Мы можем сделать это с помощью look:

puts tick #=> 0
puts tick #=> 1
puts look #=> 1
puts look #=> 1

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

Кольцевые списки

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

puts (ring :a, :b, :c).tick #=> :a

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

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

Взгляните в журнал, и вы увидите : a,: b, : c, а затем снова: a. Обратите внимание, что look возвращает 3. Вызовы .tick действуют так же, как и вызовы привычного tick - они увеличивают локальный такт во времени.

Арпеджиатор живого цикла

Настоящая мощь проявляется, когда вы смешиваете tick с кольцами и live_loop. В совокупности у нас есть все инструменты, необходимые для создания простого арпеджиатора. Нам нужно всего четыре вещи:

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

Все эти вещи можно найти в следующем коде:

notes = (ring 57, 62, 55, 59, 64)
live_loop :arp do
  use_synth :dpulse
  play notes.tick, release: 0.2
  sleep 0.125
end

Давайте посмотрим на каждую из этих строк. Сначала мы определяем кольцо нот, которые мы будем играть. Затем мы создаем live_loop с именем: arp, который обеспечит нам цикл. Каждый раз проходя цикл live_loop, мы устанавливаем наш синтезатор в: dpulse, а затем проигрываем следующую ноту в нашем кольце, используя .tick. Помните, что это увеличивает наш счетчик тактов и использует последнее значение тактов в качестве индекса в нашем кольце из нот. Наконец, мы ждем восьмой такт, прежде чем снова начать цикл.

Работа нескольких тактов одновременно

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

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

Столкновение тактов

Основная причина путаницы с системой тиков Sonic Pi заключается в том, что люди используют сразу несколько счетчиков наименованных тактов для несколько колец в одном и том же 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

Несмотря на то, что каждый live_loop имеет свой собственный независимый счетчик ударов, мы вызываем .tick дважды в одном и том же live_loop. Это означает, что такт будет увеличиваться дважды на каждый шаг времени. Это может привести к некоторым интересным полиритмам, но часто это не то, что вы хотите. Есть два решения этой проблемы. Один из вариантов - вручную вызвать tick в начале live_loop, а затем использовать .look для поиска текущего такта в каждом live_loop. Второе решение заключается в передаче уникального имени каждому вызову .tick, например, .tick (: foo) . Sonic Pi создаст и отследит отдельный счетчик тактов для каждого поименованного тика. Таким образом, вы можете работать с таким количеством тактов, которое вам нужно! См. Раздел 9.4 о поименованных тиках встроенного руководства для получения дополнительной информации.

Соединим всё вместе

Давайте соберем все эти знания оtick, ring и live_loop вместе для одного забавного финального примера. Как обычно, не относитесь к этому как к готовому произведению. Начните менять значения, поиграйте с этим и посмотрите, во что вы можете превратить это. Увидимся в следующий раз…

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

- Нарезка сэмплов

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

Звук как данные

Прежде чем мы начнем, давайте кратко рассмотрим, как работать с сэмплами. К настоящему времени вы все, надеюсь, уже играете с мощным сэмплером Sonic Pi. Если еще нет, то прямо сейчас не самое подходящее время! Загрузите Raspberry Pi, запустите Sonic Pi из меню Программирование, введите следующее в свободный буфер и затем нажмите кнопку Выполнить, чтобы услышать предварительно записанный барабанный ритм:

sample :loop_amen

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

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

Если бы мы отразили на графике звук, это был бы простой график данных со временем по оси x и положением микрофона / динамика в диапазоне от -1 до 1 по оси y. Вы можете увидеть пример такого графика на диаграмме в верхней правой части Sonic Pi.

Проигрывание части сэмпла

Итак, как же мы программируем Sonic Pi, чтобы воспроизвести сэмпл в другом порядке? Чтобы ответить на этот вопрос, нам нужно взглянуть на такие параметры sample, как start: и finish:. Они позволяют нам контролировать начальную и конечную позиции воспроизведения чисел, которые представляют звук. Значения для обоих этих вариантов представлены в виде числа между 0 и 1, где 0 это начало сэмпла, а 1 - конец. Итак, чтобы сыграть первую половину Amen Break, нам просто нужно указать finish: из 0.5:

sample :loop_amen, finish: 0.5

Мы можем добавить значение start:, чтобы воспроизвести еще меньшую часть сэмпла:

sample :loop_amen, start: 0.25, finish: 0.5

Для забавы, вы можете даже задать значение параметра finish: * перед * значением параметраstart:, и тогда указанная часть сэмпла будет воспроизведена в обратном направлении:

sample :loop_amen, start: 0.5, finish: 0.25

Изменение порядка воспроизведения сэмпла

Теперь, когда мы знаем, что сэмпл - это просто список чисел, которые можно воспроизвести в любом порядке, а также то, как воспроизводить определенную часть сэмпла, мы можем теперь начать веселиться, воспроизводя сэмпл в «неправильном» порядке.

Amen Slices

Давайте возьмем наш Amen Break и нарежем его на 8 слайсов одинакового размера, а затем перемешаем кусочки. Посмотрите на диаграмму: в верхней части А) представлен график наших исходных данных. Нарезка его на 8 слайсов дает нам B) - обратите внимание, что мы дали каждому слайсу свой цвет, чтобы легче различить их. Вы можете увидеть начальные и конечные значения каждого слайса в верхней части. Наконец, C) является одним из возможных переупорядочений слайсов. Затем мы можем воспроизвести это, чтобы создать новый ритм. Взгляните на код, чтобы сделать это:

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

мы выбираем случайный фрагмент для воспроизведения, который представлен случайным числом от 0 до 7 (помните, что мы начинаем считать с 0). Sonic Pi имеет удобную функцию именно для этого: rand_i (8). Затем мы сохраняем этот случайный индекс слайса в переменной slice_idx. Мы определяем наш slice_size, который составляет 1/8 или 0,125. Slice_size необходим для того, чтобы мы преобразовали наш slice_idx в значение между 0 и 1, чтобы мы могли использовать его в качестве нашего параметра start: . Мы вычисляем начальную позицию s путем умножения slice_idx на slice_size. Мы рассчитываем конечную позицию f, добавляя slice_size к начальной позиции s. Теперь мы можем воспроизвести слайс сэмпла, вставив значения s и f в параметрыstart: и finish:, принадлежащие sample. Перед тем, как мы начнем воспроизводить следующий слайс, нам нужно знать, как долго нужно sleep, равно длительности слайса сэмпла. К счастью, у Sonic Pi есть для нас функцияsample_duration, которая принимает все те же параметры, что и sample, и просто возвращает продолжительность. Поэтому, передавая sample_duration нашим параметрам start: и finish: , мы можем узнать длительность одного слайса. Мы упаковываем весь этот код в live_loop, чтобы циклически продолжать выбирать новые случайные фрагменты для воспроизведения.

Соединим всё вместе

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

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

- Программирование вероятностного секвенсора

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

Вероятность

Прежде чем мы сможем начать делать новые биты и синтезаторные ритмы, нам нужно быстро обратиться к основам вероятности. Это может показаться пугающим и сложным, но на самом деле это так же просто, как бросать кости - честно! Когда вы берете обычные 6-ти сторонние кости для настольных игр и бросаете их, что на самом деле происходит? Ну, во-первых, вы с одинаковой вероятностью получите 1, 2, 3, 4, 5 или 6. Фактически, учитывая, что это 6-ти сторонние кости, в среднем (если вы бросаете множество раз) вы будете получать 1 каждые 6 бросков. Это означает, что у вас есть шанс 1 к 6 бросить 1. Мы можем эмулировать броски костей в Sonic Pi с помощью функции dice. Давайте бросим с ее помощью кости 8 раз:

8.times do
  puts dice
  sleep 1
end

Обратите внимание, что журнал отображает значения от 1 до 6 так же, как если бы мы сами бросали реальные кости.

Случайные барабанные ритмы

Теперь представьте, что у вас есть барабан, и каждый раз, когда вы собирались в него ударить, вы бросали кости. Если вы получили 1, вы били в барабан, и не били всякий раз, когда выпадало другое число. Теперь у вас есть вероятностная драм-машина, работающая с вероятностью 1/6! Давайте послушаем, как это звучит:

live_loop :random_beat do
  sample :drum_snare_hard if dice == 1
  sleep 0.125
end

Давайте пробежим по каждой строке, чтобы убедиться, что нам с этим все ясно. Итак, сначала мы создаем новый live_loop с именем: random_beat, который будет постоянно повторять две строки между do и end. Первая из этих строк - это вызов sample, который будет воспроизводить предварительно записанный звук (в данном случае звук: drum_snare_hard). Однако эта строка имеет специальное условное окончание if. Это означает, что строка будет выполнена только в том случае, если оператор в правой части if равен true. В нашем случае, если «dice == 1». Это вызывает нашу функцию dice, которая, как мы видели, возвращает значение от 1 до 6. Затем мы используем оператор равенства == , чтобы проверить, равно ли это значение 1. Если это 1, то оператор сообщает true и звучит наш малый барабан. Если это не 1, тогда оператор сообщает false и малый барабан не звучит. Вторая строка просто ждет 0,125 секунды, прежде чем снова бросить кости.

Изменение вероятности

Те из вас, кто играл в ролевые игры, будут знакомы с множеством кубиков странной формы с различными диапазонами. Например, есть кости в форме тетраэдра, которые имеют 4 стороны и даже 20 сторонних кубиков в форме икосаэдра. Количество сторон на кости меняет шанс или вероятность получить 1. Чем меньше сторон, тем больше вероятность, что вы получите 1, и чем больше сторон, тем меньше вероятность. Например, с 4-х сторонними кубиками, есть один шанс к 4 получить 1, а с 20-ти сторонними кубиками есть шанс один к 20. К счастью, в Sonic Pi для этого есть удобная функция one_in. Давай поиграем:

live_loop :different_probabilities do
  sample :drum_snare_hard if one_in(6)
  sleep 0.125
end

Запустите живой цикл выше, и вы услышите уже знакомый случайный ритм. Но не останавливайте выполнение кода. Вместо этого измените 6 на другое значение, например ` 2 или 20`, и снова нажмите кнопку Выполнить. Обратите внимание, что более низкие числа означают, что малый барабан звучит чаще, а более высокие числа означают, что реже. Вы делаете музыку с вероятностью!

Комбинирование вероятности

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

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

Снова запустите код выше и затем начните изменять вероятности, чтобы повлиять на ритм. Кроме того, попробуйте изменить сэмплы, чтобы создать совершенно новое звучание кода. Например, попробуйте изменить : drum_cymbal_closed на: bass_hit_c, чтобы добавить баса!

Повторяющийся ритм

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

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

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

Соединим всё вместе

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

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

- Амплитудная модуляция

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

Нарезая амплитуду

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

synth :prophet, note: :e1, release: 8, cutoff: 70
synth :prophet, note: :e1 + 4, release: 8, cutoff: 80

Теперь давайте пропустим это через эффект : slicer :


with_fx :slicer do
  synth :prophet, note: :e1, release: 8, cutoff: 70
  synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
end

Послушайте, как работает слайсер - он как будто заглушает и включает звук в регулярном ритме. Также обратите внимание, как : slicer влияет на все аудио, сгенерированное между блоками do / end. Вы можете контролировать скорость, с которой он включает и выключает звук, с помощью опции phase:, которая сокращает длительность фазы. Его значение по умолчанию равно 0.25, что означает 4 раза в секунду при значении BPM по умолчанию 60. Давайте сделаем это быстрее:

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

Теперь поиграйте с разными значениями продолжительности phase: сами. Попробуйте более длинные и короткие значения. Посмотрите, что происходит, когда вы выбираете действительно короткое значение. Кроме того, попробуйте различные синтезаторы, такие как : beep или: dsaw и другие ноты. Взгляните на следующую диаграмму, чтобы увидеть, как различные значения phase: изменяют количество изменений амплитуды за такт.

Длительность фазы

Продолжительность фазы - это продолжительность одного цикла включения / выключения. Поэтому меньшие значения заставят эффект включаться и выключаться намного быстрее, чем большие значения. Хорошие значения для начала игры: 0.125, 0.25, 0.5 и 1.

Контролируя волны

По умолчанию эффект : slicer использует прямоугольную волну для управления амплитудой во времени. Вот почему мы слышим, как амплитуда включается на некоторое время, затем сразу отключается на некоторое время, затем снова включается. Оказывается, прямоугольная волна - это всего лишь одна из 4 различных управляющих волн, которые поддерживаются : slicer. Другие это пила, треугольник и (ко)синус. Посмотрите на диаграмму ниже, чтобы увидеть, как они выглядят. Мы также можем услышать, как они звучат. Например, следующий код использует (кo)синус в качестве управляющей волны. Послушайте, как звук не включается и не выключается внезапно, а плавно затухает:

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

Поиграйте с разными формами волн, изменив параметр wave: на 0 для пилы, 1 для квадрата, 2 для треугольника и 3 для синуса. Посмотрите, как звучат разные волны с разными параметрами phase:.

Каждая из этих волн может быть инвертирована с помощью опции invert_wave:, который переворачивает ее на оси y. Например, в одной фазе пилообразная волна обычно начинается с высокой отметки и медленно опускается, а затем возвращается к вершине. С помощью invert_wave: 1 он медленно поднимется, прежде чем снова спрыгнуть вниз. Кроме того, управляющая волна может быть запущена в разных точках с помощью параметра phase_offset:, который должен быть значением между 0 и 1. Играя с параметрами phase:, wave:, invert_wave: и phase_offset, вы можете кардинально изменить способ изменения амплитуды во времени.

Длительность фаз

Настройка уровня вашего звука

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

with_fx :slicer, amp_min: 0.25, amp_max: 0.75, wave: 3, phase: 0.25 do
  synth :saw, release: 8
end

Это как если бы взять ручку регулировки громкости на своем hi-fi и немного переместить ее вверх и вниз, чтобы звук «качался» внутрь и наружу динамика.

Вероятности

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

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

Послушайте, как у нас сейчас интересно пульсирует ритм. Попробуйте изменить параметр probability: на другое значение между 0 и 1. Значения, близкие к 0, будут иметь больше места между каждым отдельным звуком, поскольку вероятность того, что звук будет срабатывать, будет намного ниже.

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

Наконец, с помощью параметра prob_pos:, вы можете изменить положение ‘resting’ для управляющей волны с 0 на любую другую позицию, когда проверка вероятности возвращает ложь, а не истину:

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

Нарезаем биты

Есть одна очень забавная вещь - использовать : slicer для нарезки барабанного ритма:

with_fx :slicer, phase: 0.125 do
  sample :loop_mika
end

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

Изменяем темп

Как мы уже видели, изменение значения BPM по умолчанию с помощью use_bpm приведет к увеличению или уменьшению времени ожидания и длительности огибающей синтезатора в соответствии с тактом. Эффект : slicer также учитывает это, поскольку параметр phase: фактически измеряется в тактах, а не секундах. Поэтому мы можем исправить проблему, возникшую с loop_amen выше, изменив BPM в соответствии с примером:

use_sample_bpm :loop_amen
with_fx :slicer, phase: 0.125 do
  sample :loop_amen
end

Соединим всё вместе

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

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

- Пять техник лайв-кодинга

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

1. Помнить сокращения

Первый совет для лайвкодинга с Sonic Pi - начать использовать сокращения. Например, вместо того, чтобы тратить драгоценное время на то, чтобы дотянуться до мыши, переместить ее на кнопку Выполнить и сделать клик, вы можете просто одновременно нажать «alt» и «r», что намного быстрее и позволяет держать пальцы на клавиатуре наготове. для дальнейшего редактирования. Вы можете найти сокращения для основных кнопок вверху окна программы, наведя на них курсор мыши. См. Раздел 10.2 встроенного руководства для полного списка сокращений.

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

2. Складывайте свои звуки вручную

Теперь вы можете мгновенно запускать код с клавиатуры. И вы сразу же можете применить этот навык для нашей второй техники, которая заключается в наложении звуков вручную. Вместо ‘композирования’ с использованием большого количества вызовов play и sample, разделенных вызовами sleep, у нас будет один вызов play, который мы будем запускать вручную с помощью alt-r. Давай попробуем. Введите следующий код в свободный буфер:

synth :tb303, note: :e2 - 0, release: 12, cutoff: 90

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

synth :tb303, note: :e2 - 4, release: 12, cutoff: 90

Теперь снова нажмите Выполнить, чтобы услышать оба звуковых слоя одновременно. Это связано с тем, что кнопка Выполнить в Sonic Pi не ждет завершения предыдущего кода, а сразу же запускает измененный код на выполнение. Это означает, что вы можете легко наложить много звуков вручную с незначительными или существенными изменениями между каждым запуском. Например, попробуйте изменить оба параметра note: и cutoff:, а затем повторно запустить.

Вы также можете попробовать эту технику с длинными абстрактными сэмплами. Например:

sample :ambi_lunar_land, rate: 1

Запустите сэмпл, а затем постепенно делите параметр rate: вдвое между каждым нажатием Выполнить. Начав с 1 , введите 0.5 , затем ` 0.25 и наконец 0.125. Можете даже попробовать некоторые отрицательные значения, такие как -0.5`. Накладывайте звуки один на другой и посмотрите, где вы можете это использовать. И, наконец, попробуйте добавить немного эффектов.

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

3. Овладейте живыми циклами

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

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

4. Используйте мастер-миксер

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

set_mixer_control! lpf: 50

После запуска этого кода ко всем уже существующим и новым звукам будет применен фильтр низких частот, и, следовательно, они будут звучать более приглушенно. Заметьте, это означает, что эти значения микшера остаются таковыми, пока не будут изменены снова. Однако, если вы хотите, вы всегда можете вернуть микшер обратно в состояние по умолчанию с помощью reset_mixer!. Вот некоторые из поддерживаемых параметров: pre_amp:, lpf: hpf: и amp:. Полный список см. Во встроенной документации для set_mixer_control!.

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

set_mixer_control! lpf_slide: 16, lpf: 30

Затем вы можете быстро вернуться к высокому значению с помощью:

set_mixer_control! lpf_slide: 1, lpf: 130

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

5. Практика

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

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

Соединим всё вместе

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


- 8 Советов, которые помогут вам при лайв-кодинге

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

Практикуйтесь регулярно

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

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

Научитесь слепому набору

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

Практический совет #2 - тренируйте слепой набор. Есть множество приложений, вебсайтов и даже игр, которые могут помочь вам в этом деле. Найдите то, которое вам нравится и поупражняйтесь в нём, пока у вас не получится набирать текст не глядя.

Программируйте стоя

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

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

Практикуйтесь в настройке вашего оборудования

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

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

Экспериментируйте в музыке

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

Практический совет № 5 - тратьте время на создание даже таких звуков и музыки, которые вам не нравятся. Постарайтесь найти время для изучения новых звуков и идей. Не волнуйтесь, это звучит ужасно, и не так, как бы вы хотели. Когда вы экспериментируете таким образом, вы увеличиваете вероятность наткнуться на звук или комбинацию звуков, которые вы полюбите! Даже если 99% ваших звуков плохие, этот 1% может стать главным риффом или вступлением к вашему новому треку. Забудьте о том, что у вас не выходит все сразу, и помните, что вам может пригодиться часть того, что вы сделали прямо сейчас. Это даже проще, когда вы пишете музыку с кодом - просто нажмите «Сохранить»!

Учитесь слышать код

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

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

Устраните все отвлекающие факторы

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

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

Ведите дневник практики

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

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

Соединим всё вместе

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


- Растягивание сэмплов

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

Замедление сэмплов

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

sample :guit_em9, rate: 1

Если мы укажем rate: значение 1, то сэмпл воспроизведется с нормальной скоростью. Если мы хотим воспроизвести его с половиной начальной скорости, мы просто используем для rate: значение 0.5:

sample :guit_em9, rate: 0.5

Обратите внимание, что это производит два эффекта на аудио. Во-первых, сэмпл звучит ниже по высоте, а во-вторых, для воспроизведения требуется вдвое больше времени. Мы можем выбрать все более низкие значения, двигаясь в сторону 0. Так rate: в значении ` 0.25 - это четверть скорости, 0.1` - это десятая часть скорости и т. д. Попробуйте поиграть с некоторыми низкими значениями и посмотрите, как вы можете превратить звук в низкий грохот.

Ускорение сэмплов

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

sample :loop_amen, rate: 1

Теперь давайте немного ускорим:

sample :loop_amen, rate: 1.5

Ха! Мы просто сменили музыкальные жанры из техно-стиля в джангл. Обратите внимание, что высота каждого удара барабана стала выше, а также как ускоряется и весь ритм. Теперь попробуйте еще более высокие значения и посмотрите, насколько высокими и короткими вы можете сделать барабанную петлю. Например, если вы используете значение 100, барабанная петля превращается в щелчок!

Обратная передача

Теперь, я уверен, что многие из вас думают об одном и том же прямо сейчас … «что если вы используете отрицательное значение для rate:?». Отличный вопрос! Давайте подумаем об этом на мгновение. Если наш параметр rate: обозначает скорость, с которой воспроизводится сэмпл, где 1 - нормальная скорость, 2 - двойная скорость, 0.5 - половинная скорость, -1 должно означать задом наперед! Давайте попробуем это на малом барабане. Сначала воспроизведите его с нормальной скоростью:

sample :elec_filt_snare, rate: 1

Теперь проиграем это в обратном направлении:

sample :elec_filt_snare, rate: -1

Конечно, вы можете играть в обратном направлении в два раза быстрее со значением -2 или назад в половину скорости со значением -0.5. Теперь поиграйте с разными отрицательными значениями и получайте удовольствие. Это особенно забавно с сэмплом : misc_burp!

Сэмпл, его скорость воспроизведения и высота тона

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

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

Сэмпл аналогового сигнала - это не что иное, как множество чисел (x, y, координаты), которые при перенесении на график воссоздают с той или иной точностью исходную звуковую волну. Смотрите рисунок D, где каждая точка представляет координату. Чтобы преобразовать координаты обратно в звук, компьютер соединяет каждое значение x с со соответствующим значением y и отправляет в динамики. Хитрость в том, что скорость, с которой компьютер работает с числами х, не обязательно должна совпадать со скоростью, с которой они были записаны. Другими словами, пространство (представляющее количество времени) между каждой точкой координат может быть растянуто или сжато. Таким образом, если компьютер будет проходить через значения x быстрее, чем исходная скорость, это приведет к сжатию координат ближе друг к другу, что приведет к более высокому тону сигнала. Также это сделает звуковой сигнал короче, так как мы будем проходить все координаты быстрее. Это показано на рисунке E.

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

Модуляция тональности звука

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

sample :bass_trance_c, rate: 1
sample :bass_trance_c, rate: 2
sample :bass_trance_c, rate: 0.5

Однако что, если мы просто хотим изменить скорость так, чтобы высота звука повышалась на один полутон (одна клавиша на фортепиано)? Sonic Pi делает это очень легко с помощью параметра rpitch::

sample :bass_trance_c
sample :bass_trance_c, rpitch: 3
sample :bass_trance_c, rpitch: 7

Если вы посмотрите в журнал, то заметите, что rpitch: в значении 3 фактически соответствует скорости 1.1892, а rpitch: в значении 7 соответствует скорости 1.4983. Наконец, мы можем даже объединить параметрыrate: и rpitch::

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

Соединим всё вместе

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

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

- Аддитивный синтез

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

Простые комбинации

Давайте начнем с самого основного звука -простой синусоиды с чистыми тонами:

synth :sine, note: :d3

Теперь давайте посмотрим, как это звучит в сочетании с прямоугольной волной:

synth :sine, note: :d3
synth :square, note: :d3

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

Смешивание со вкусом

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

synth :sine, note: :d3
synth :square, note: :d3
synth :tri, note: :d4, amp: 0.4

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

Расстройка осцилляторов

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

detune = 0.7
synth :square, note: :e3
synth :square, note: :e3 + detune

Если мы расстроем наши прямоугольные волны на 0,7 ноты, мы услышим что-то, что, возможно, звучит не в гармонии или не правильно - как «плохая» нота. Однако, когда мы приближаемся к 0, это будет звучать все менее и менее заметно, так как высота звука двух волн становится все ближе и ближе. Попробуйте сами! Измените значение параметра detune: с 0.7 на 0.5 и прослушайте новый звук. Попробуйте 0.2, 0.1, 0.05, 0. Каждый раз, когда вы меняете значение, прислушайтесь и посмотрите, можете ли вы услышать, как меняется звук. Обратите внимание, что низкие значения расстройки, такие как 0.1, производят действительно хороший «толстый» звук, при этом оба немного отличающихся тона взаимодействуют друг с другом интересным, часто удивительным, способом.

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

Амплитудная огибающая

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

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

В приведенном выше примере я смешал шумовой перкуссионный элемент с настойчивым грохочущим призвуком. Это было достигнуто в первую очередь за счет использования двух синтезаторов шума со средними значениями среза частоты фильтра (90 и 100) и с использованием короткого времени высвобождения (release) наряду с шумом с более длительным временем высвобождения, но с низким значением частоты среза фильтра (что делает шум менее четким и более гудящим.)

Соединим всё вместе

Давайте объединим все эти методы, чтобы увидеть, сможем ли мы использовать аддитивный синтез для воссоздания простого звука колокольчика. Я разбил этот пример на четыре раздела. Во-первых, у нас есть секция «hit», которая является начальной частью звука колокольчика, поэтому мы используем быструю огибающую (например, release: около 0.1). Затем у нас есть длинный участок звука колокольчика, в котором я использую чистый звук синусоиды. Обратите внимание, что я часто увеличиваю ноту примерно на 12 и 24, которые представляют собой количество нот в одной и двух октавах. Я также добавил пару низких синусоидальных волн, чтобы придать звуку немного баса и глубины. Наконец, я использовал define, чтобы обернуть мой код в функцию, которую затем я могу использовать для воспроизведения мелодии. Попробуйте сыграть свою собственную мелодию, а также поиграться с содержанием функции : bell, пока не создадите свой собственный сумасшедший звук для игры!

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

- Субтрактивный синтез

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

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

Комплексный исходный сигнал

Чтобы звук хорошо работал в субтрактивном синтезе, он должен быть достаточно насыщенным и интересным. Это не значит, что нам нужно что-то чрезвычайно сложное - на самом деле, стандартная волна : square или: saw сделает что нужно:

synth :saw, note: :e2, release: 4

Обратите внимание, что этот звук уже довольно интересен и содержит много разных частот выше : e2 (E второй октавы на фортепиано), которые добавляются для создания тембра. Если для вас это пока не особенно понятно, попробуйте сравнить его с : beep:

synth :beep, note: :e2, release: 4

Поскольку синтезатор : beep - это просто синусоида, вы услышите более чистый тон и только в регистре : e2 и не буде выше него никаких хрустящих / гудящих звуков, которые вы слышали в : saw. Именно с этими призвуками и вариациями чистой синусоидальной волны мы можем играть, используя субтрактивный синтез.

Фильтры

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

with_fx :lpf, cutoff: 100 do
  synth :saw, note: :e2, release: 4
end

Если вы внимательно прослушаете, вы услышите, как некоторые из этих шумных и хрустящих звуков были удалены. Фактически, все частоты в звуке выше ноты 100 были уменьшены или удалены, и только те, что ниже, все еще присутствуют в звуке. Попробуйте изменить значение cutoff:, укажите ему на более низкие ноты, скажем 70, а затем 50 и сравните звуки.

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

with_fx :hpf, cutoff: 90 do
  synth :saw, note: :e2, release: 4
end

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

Low Pass Filter

Фильтр нижних частот является настолько важной частью каждого субтрактивного инструментария синтеза, что стоит более глубоко взглянуть на его работу. Эта диаграмма показывает одну и ту же звуковую волну (синтезатор : prophet) с различной степенью фильтрации. Вверху в разделе A показана звуковая волна без фильтрации. Обратите внимание, что форма волны очень острая и содержит много острых краев. Именно эти жесткие, острые углы создают высокие хрустящие / шумные части звука. В разделе B показан фильтр нижних частот в действии - обратите внимание, что он менее острый и более округлый, чем форма волны выше. Это означает, что у звука будет меньше высоких частот, что придаст ему более мягкий округлый вид. В разделе C показан фильтр нижних частот с довольно низким значением отсечки - это означает, что еще больше высоких частот было удалено из сигнала, что привело к еще более мягкой, округлой форме волны. Наконец, обратите внимание, как размер формы волны, которая представляет амплитуду, уменьшается при переходе от А к С. Субтрактивный синтез работает путем удаления частей сигнала, что означает, что общая амплитуда уменьшается по мере того, как объем фильтрации увеличивается.

Модуляция фильтра

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

with_fx :lpf, cutoff: 50 do |fx|
  control fx, cutoff_slide: 3, cutoff: 130
  synth :prophet, note: :e2, sustain: 3.5
end

Давайте кратко рассмотрим, что здесь происходит. Сначала мы запускаем FX-блок : lpf как обычно с начальным cutoff: с очень низким значением 20. Тем не менее, первая строка также заканчивается странным | fx | в конце. Это необязательная часть синтаксиса with_fx, которая позволяет вам напрямую называть и управлять запущенным эффектом синтезатора. Строка 2 управляет таким эффектом, устанавливая для параметра cutoff_slide: значение 4, а целевое значение cutoff: должно быть 130. Эффект теперь начнет снижать значение параметра cutoff: с 50 до 130 в течение 3 тактов. Наконец, мы запускаем синтезатор, чтобы слышать эффект модулированного фильтра нижних частот.

Соединим всё вместе

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

Давайте закончим, разработав функцию, которая будет воспроизводить новый звук, созданный с субтрактивным синтезом. Посмотрите, сможете ли вы выяснить, что здесь происходит, - и для продвинутых читателей Sonic Pi - посмотрите, сможете ли вы понять, почему я завернул все в вызов функции at (пожалуйста, отправьте ответы на @samaaron в 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

- Creative coding in the classroom with Sonic Pi

(This article was published in issue 9 of the Hello World Magazine)

Code is one of the most creative media that humans have created. The initially obscure symbols of parentheses and lambdas are not just deeply rooted in science and mathematics, they are the closest we have managed to get to casting the same kind of magical spells as Gandalf and Harry Potter. I believe that this provides a powerful means of engagement in our learning spaces. Through the magic of code we are able to conjure up individually meaningful stories and learning experiences.

We are surrounded by magical experiences. From the sleight of hand of a stage magician making the ball disappear into thin air, to the wonder of seeing your favourite band perform on a big stage. It is these “wow” moments that inspire us to pick up a magic book and learn the French Drop or to start jamming power chords on an old guitar. How might we create similarly deep and lasting senses of wonder that will motivate people to practice and learn the fundamentals of programming?

Musical Engines and Notation

The histories of music and computers have been intricately woven together since the inception of computing machines, or “engines” as Charles Babbage’s powerful analytical engine was called. Back in 1842 the Mathematician Ada Lovelace, who worked very closely with Babbage, saw the creative potential of these engines. Whilst these first engines had originally been designed to accurately solve hard maths problems, Ada dreamt about making music with them:

”..the engine might compose elaborate and scientific pieces of music of any degree of complexity or extent.” Ada Lovelace, 1842.

Of course, today in 2019 much of our music, regardless of genre, has either been composed, produced or mastered with a digital computer. Ada’s dream came true. It is even possible to trace the history back even further. If you see coding as the art of writing sequences of special symbols that instruct a computer to do specific things, then musical composition is a very similar practice. In Western music, the symbols are black dots positioned on a stave of lines that tell the musician which notes to play and when. Intriguingly, if we trace the roots of Western music notation back to the Italian Benedictine monk, Guido d’Arezzo, we find that the dots and lines system that modern orchestras use is just one of a number of notation systems he worked on. Some of the others were much closer to what we might now see as code.

Get

Sonic Pi Performances

Лайв-кодинг

Sonic Pi has been used to perform in a wide range of venues such as school halls, nightclubs, outdoor stages at musical festivals, college chapels and prestigious music venues. For example the amazing Convo project which brought 1000 children together in the Royal Albert Hall to perform an ambitious new composition by composer Charlotte Harding. The piece was written for traditional instruments, choirs, percussion and Sonic Pi code. The pop-artist Jylda also performed with Sonic Pi in the Sage Gateshead for the Thinking Digital Conference, where she created a unique live-coded improvised remix of her song Reeled.

Sonic Pi in the Royal Albert Hall Sonic Pi used as one of the instruments as part of Convo at the Royal Albert Hall. Photo credit: Pete Jones.

Live coding in the classroom

Sonic Pi is a code-based music creation and performance tool that builds on all of these ideas. Unlike the majority of computing education software, it is both simple enough to use for education and also powerful enough for professionals. It has been used to perform in international music festivals, used to compose in a range of styles from classical, EDM and heavy metal, and was even reviewed in the Rolling Stone magazine. It has a diverse community of over 1.5 million live coders with a variety of backgrounds all learning and sharing their ideas and thoughts through the medium of code. It is free to download for Mac, PC and Raspberry Pi and includes a friendly tutorial that assumes you know nothing about either code or music.

Sonic Pi was initially conceived as a response to the UK’s newly released Computing curriculum in 2014. The goal was to find a motivating and fun way to teach the fundamentals of programming. It turns out that there is a lot in common and it’s huge fun to explain sequencing as melody, iteration as rhythm, conditionals as musical variety. I developed the initial designs and first iterations of the platform with Carrie Anne Philbin, who brought a teacher’s perspective to the project. Since then, Sonic Pi has undergone iterative improvements thanks to the feedback gained from observing learners and collaborating directly with educators in the classroom. A core design philosophy was to never add a feature that couldn’t be easily taught to a 10 year old child. This meant that most ideas had to be heavily refined and reworked until they were simple enough. Making things simple whilst keeping them powerful continues to be the hardest part of the project.

In order to provide the magical motivation, Sonic Pi’s design was never limited to a pure focus on education. Ideally there would be famous musicians and performers using Sonic Pi as a standard instrument alongside guitars, drums, vocals, synths, violins, etc. These performers would then act as motivational role models demonstrating the creative potential of code. For this to be possible sufficient focus and effort therefore had to be placed on making it a powerful instrument whilst still keeping it simple enough for 10 year olds to pick up. In addition to educators, I also worked directly with a variety of different artists in classrooms, art galleries, studios and venues in the early stages of Sonic Pi’s development. This provided essential feedback which enabled Sonic Pi to grow and ultimately flourish as a tool for creative expression.

There were a number of exciting and unexpected side effects of this dual focus on education and professional musicians. Many of the features are beneficial to both groups. For example, a lot of effort has been put into making error messages more friendly and useful (rather than being a huge complicated mess of jargon). This turns out to be very useful when you write a bug while performing in front of thousands of people. Additionally, functionality such as playing studio quality audio samples, adding audio effects, providing access to live audio from the microphone all turn out to make the learning experience more fun, rewarding and ultimately meaningful.

The Sonic Pi community continues to grow and share amazing code compositions, lesson plans, musical algorithms, and much more. Much of this happens on our friendly forum in_thread (in-thread.sonic-pi.net) which is home to a very diverse group of people that includes educators, musicians, programmers, artists and makers. It is a real joy to see people learn to use code to express themselves in new ways and for that in turn to inspire others to do the same.

- Some fun capabilities

From a Computer Science perspective, Sonic Pi provides you with the building blocks to teach you the basics as found in the UK’s curriculum such as sequencing, iteration, conditionals, functions, data structures, algorithms, etc. However, it also builds on a number of important and relevant concepts which have become adopted in mainstream industry such as concurrency, events, pattern matching, distributed computing and determinism - all whilst keeping things simple enough to explain to a 10 year old child.

Get

play 70

A melody can be constructed with one more command, sleep:

play 72
sleep 0.5
play 75
sleep 0.5
play 79

In this example, we play the note 70 (roughly the 70th note on a piano), wait for 1 second, play note 72, wait for half a second and then play note 75. What’s interesting here is that with just two commands we have access to pretty much all of Western notation (which notes to play and when) and learners can code any melody they’ve ever heard. This leads to huge variety in expressive outcomes whilst focussing on the same computing concept: sequencing in this case.

Taking ideas from the professional music world, we can also play back any recorded sound. Sonic Pi can play any audio file on your computer but also has a number of sounds built-in to make things easy to get started:

sample :loop_amen

This code will play back the drum break which was a pillarstone to early hip-hop, Drum and Bass and Jungle. For example, a number of early hip-hop artists played this drum break back at half speed to give it a more laid-back feeling:

sample :loop_amen, rate: 0.5

In the 90s a number of music scenes burst out of new technology which enabled artists to take drum breaks like this apart and reassemble in a different order. For example:

sample :loop_amen

случайный


- Необходимые знания

Этот раздел будет охватывать некоторые очень полезные - на самом деле даже необходимые знания для получения максимальной отдачи от вашего опыта работы с 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